summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2019-07-19 12:13:00 -0300
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2019-07-19 12:13:00 -0300
commit440a5ee78c8592230780310c9c8d8c2ba1700cb1 (patch)
tree30d361cbe23eb652f8874e580750ca65fcca5b52
parentdc07719b0dbc4f2df0f42e34e18be1e0ac4fa2c3 (diff)
downloadlua-440a5ee78c8592230780310c9c8d8c2ba1700cb1.tar.gz
lua-440a5ee78c8592230780310c9c8d8c2ba1700cb1.tar.bz2
lua-440a5ee78c8592230780310c9c8d8c2ba1700cb1.zip
Fixed bug for emergency collection in upvalue creation
When creating an upvalue, an emergency collection can collect the previous upvalue where the new one would be linked. The following code can trigger the bug, using valgrind on Lua compiled with the -DHARDMEMTESTS option: local x; local y (function () return y end)(); (function () return x end)()
-rw-r--r--lfunc.c14
-rw-r--r--lfunc.h2
-rw-r--r--lvm.c2
3 files changed, 10 insertions, 8 deletions
diff --git a/lfunc.c b/lfunc.c
index 9f91ad4f..f7edf56b 100644
--- a/lfunc.c
+++ b/lfunc.c
@@ -82,20 +82,22 @@ static UpVal *newupval (lua_State *L, int tbc, StkId level, UpVal **prev) {
82 82
83 83
84/* 84/*
85** Find and reuse, or create if it does not exist, a regular upvalue 85** Find and reuse, or create if it does not exist, an upvalue
86** at the given level. 86** at the given level and set it to the given slot.
87*/ 87*/
88UpVal *luaF_findupval (lua_State *L, StkId level) { 88void luaF_setupval (lua_State *L, StkId level, UpVal **slot) {
89 UpVal **pp = &L->openupval; 89 UpVal **pp = &L->openupval;
90 UpVal *p; 90 UpVal *p;
91 lua_assert(isintwups(L) || L->openupval == NULL); 91 lua_assert(isintwups(L) || L->openupval == NULL);
92 while ((p = *pp) != NULL && uplevel(p) >= level) { /* search for it */ 92 while ((p = *pp) != NULL && uplevel(p) >= level) { /* search for it */
93 *slot = p;
93 if (uplevel(p) == level && !isdead(G(L), p)) /* corresponding upvalue? */ 94 if (uplevel(p) == level && !isdead(G(L), p)) /* corresponding upvalue? */
94 return p; /* return it */ 95 return; /* found it */
95 pp = &p->u.open.next; 96 pp = &p->u.open.next;
96 } 97 }
97 /* not found: create a new upvalue after 'pp' */ 98 /* not found: create a new upvalue after 'pp' (which is
98 return newupval(L, 0, level, pp); 99 anchored in 'slot', in case of an emergency collection) */
100 *slot = newupval(L, 0, level, pp);
99} 101}
100 102
101 103
diff --git a/lfunc.h b/lfunc.h
index 0ed79c48..72fc913a 100644
--- a/lfunc.h
+++ b/lfunc.h
@@ -57,7 +57,7 @@ LUAI_FUNC Proto *luaF_newproto (lua_State *L);
57LUAI_FUNC CClosure *luaF_newCclosure (lua_State *L, int nelems); 57LUAI_FUNC CClosure *luaF_newCclosure (lua_State *L, int nelems);
58LUAI_FUNC LClosure *luaF_newLclosure (lua_State *L, int nelems); 58LUAI_FUNC LClosure *luaF_newLclosure (lua_State *L, int nelems);
59LUAI_FUNC void luaF_initupvals (lua_State *L, LClosure *cl); 59LUAI_FUNC void luaF_initupvals (lua_State *L, LClosure *cl);
60LUAI_FUNC UpVal *luaF_findupval (lua_State *L, StkId level); 60LUAI_FUNC void luaF_setupval (lua_State *L, StkId level, UpVal **slot);
61LUAI_FUNC void luaF_newtbcupval (lua_State *L, StkId level); 61LUAI_FUNC void luaF_newtbcupval (lua_State *L, StkId level);
62LUAI_FUNC int luaF_close (lua_State *L, StkId level, int status); 62LUAI_FUNC int luaF_close (lua_State *L, StkId level, int status);
63LUAI_FUNC void luaF_unlinkupval (UpVal *uv); 63LUAI_FUNC void luaF_unlinkupval (UpVal *uv);
diff --git a/lvm.c b/lvm.c
index d9bd0ab3..d3e05199 100644
--- a/lvm.c
+++ b/lvm.c
@@ -697,7 +697,7 @@ static void pushclosure (lua_State *L, Proto *p, UpVal **encup, StkId base,
697 setclLvalue2s(L, ra, ncl); /* anchor new closure in stack */ 697 setclLvalue2s(L, ra, ncl); /* anchor new closure in stack */
698 for (i = 0; i < nup; i++) { /* fill in its upvalues */ 698 for (i = 0; i < nup; i++) { /* fill in its upvalues */
699 if (uv[i].instack) /* upvalue refers to local variable? */ 699 if (uv[i].instack) /* upvalue refers to local variable? */
700 ncl->upvals[i] = luaF_findupval(L, base + uv[i].idx); 700 luaF_setupval(L, base + uv[i].idx, &ncl->upvals[i]);
701 else /* get upvalue from enclosing function */ 701 else /* get upvalue from enclosing function */
702 ncl->upvals[i] = encup[uv[i].idx]; 702 ncl->upvals[i] = encup[uv[i].idx];
703 luaC_objbarrier(L, ncl, ncl->upvals[i]); 703 luaC_objbarrier(L, ncl, ncl->upvals[i]);