aboutsummaryrefslogtreecommitdiff
path: root/ldo.c
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2021-02-27 12:56:09 -0300
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2021-02-27 12:56:09 -0300
commitf9d857a81b87b695c1e3b34f1e7fe55884d1288f (patch)
tree6793853d39d5224971543b79c0ba3d3d45d536f7 /ldo.c
parent1537d6680bb66dc2484e11815bc2cd0e31ca39cc (diff)
downloadlua-f9d857a81b87b695c1e3b34f1e7fe55884d1288f.tar.gz
lua-f9d857a81b87b695c1e3b34f1e7fe55884d1288f.tar.bz2
lua-f9d857a81b87b695c1e3b34f1e7fe55884d1288f.zip
Stack reallocation done in two phases
$he stack reallocation is done in two steps (allocation + free) because the correction of the pointers pointing into the stack must be done while both addresses (the old stack and the new one) are valid. In ISO C, any pointer use after the pointer has been deallocated is undefined behavior. The compiler option '-fsanitize=pointer-subtract' (plus what it needs to work) complained about the old implementation.
Diffstat (limited to 'ldo.c')
-rw-r--r--ldo.c28
1 files changed, 21 insertions, 7 deletions
diff --git a/ldo.c b/ldo.c
index 7c9ce06e..7135079b 100644
--- a/ldo.c
+++ b/ldo.c
@@ -160,8 +160,6 @@ int luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud) {
160static void correctstack (lua_State *L, StkId oldstack, StkId newstack) { 160static void correctstack (lua_State *L, StkId oldstack, StkId newstack) {
161 CallInfo *ci; 161 CallInfo *ci;
162 UpVal *up; 162 UpVal *up;
163 if (oldstack == newstack)
164 return; /* stack address did not change */
165 L->top = (L->top - oldstack) + newstack; 163 L->top = (L->top - oldstack) + newstack;
166 L->tbclist = (L->tbclist - oldstack) + newstack; 164 L->tbclist = (L->tbclist - oldstack) + newstack;
167 for (up = L->openupval; up != NULL; up = up->u.open.next) 165 for (up = L->openupval; up != NULL; up = up->u.open.next)
@@ -179,19 +177,35 @@ static void correctstack (lua_State *L, StkId oldstack, StkId newstack) {
179#define ERRORSTACKSIZE (LUAI_MAXSTACK + 200) 177#define ERRORSTACKSIZE (LUAI_MAXSTACK + 200)
180 178
181 179
180/*
181** Reallocate the stack to a new size, correcting all pointers into
182** it. (There are pointers to a stack from its upvalues, from its list
183** of call infos, plus a few individual pointers.) The reallocation is
184** done in two steps (allocation + free) because the correction must be
185** done while both addresses (the old stack and the new one) are valid.
186** (In ISO C, any pointer use after the pointer has been deallocated is
187** undefined behavior.)
188** In case of allocation error, raise an error or return false according
189** to 'raiseerror'.
190*/
182int luaD_reallocstack (lua_State *L, int newsize, int raiseerror) { 191int luaD_reallocstack (lua_State *L, int newsize, int raiseerror) {
183 int lim = stacksize(L); 192 int oldsize = stacksize(L);
184 StkId newstack = luaM_reallocvector(L, L->stack, 193 int i;
185 lim + EXTRA_STACK, newsize + EXTRA_STACK, StackValue); 194 StkId newstack = luaM_reallocvector(L, NULL, 0,
195 newsize + EXTRA_STACK, StackValue);
186 lua_assert(newsize <= LUAI_MAXSTACK || newsize == ERRORSTACKSIZE); 196 lua_assert(newsize <= LUAI_MAXSTACK || newsize == ERRORSTACKSIZE);
187 if (l_unlikely(newstack == NULL)) { /* reallocation failed? */ 197 if (l_unlikely(newstack == NULL)) { /* reallocation failed? */
188 if (raiseerror) 198 if (raiseerror)
189 luaM_error(L); 199 luaM_error(L);
190 else return 0; /* do not raise an error */ 200 else return 0; /* do not raise an error */
191 } 201 }
192 for (; lim < newsize; lim++) 202 /* number of elements to be copied to the new stack */
193 setnilvalue(s2v(newstack + lim + EXTRA_STACK)); /* erase new segment */ 203 i = ((oldsize <= newsize) ? oldsize : newsize) + EXTRA_STACK;
204 memcpy(newstack, L->stack, i * sizeof(StackValue));
205 for (; i < newsize + EXTRA_STACK; i++)
206 setnilvalue(s2v(newstack + i)); /* erase new segment */
194 correctstack(L, L->stack, newstack); 207 correctstack(L, L->stack, newstack);
208 luaM_freearray(L, L->stack, oldsize + EXTRA_STACK);
195 L->stack = newstack; 209 L->stack = newstack;
196 L->stack_last = L->stack + newsize; 210 L->stack_last = L->stack + newsize;
197 return 1; 211 return 1;