diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2022-05-23 10:38:03 -0300 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2022-05-23 10:38:03 -0300 |
commit | 4a00f61276a9a38b0427fbae3dbbd86dfb5a0749 (patch) | |
tree | 16ed717a2f4b79bad0743c2a8888ba55e013a309 | |
parent | 42d40581dd919fb134c07027ca1ce0844c670daf (diff) | |
download | lua-4a00f61276a9a38b0427fbae3dbbd86dfb5a0749.tar.gz lua-4a00f61276a9a38b0427fbae3dbbd86dfb5a0749.tar.bz2 lua-4a00f61276a9a38b0427fbae3dbbd86dfb5a0749.zip |
'lua_checkstack' doesn't need to check stack overflow
'luaD_growstack' already checks that. This commit also fixes an
internal bug in 'luaD_growstack': a large 'n' could cause an arithmetic
overflow when computing 'needed'.
-rwxr-xr-x | all | 2 | ||||
-rw-r--r-- | lapi.c | 9 | ||||
-rw-r--r-- | ldo.c | 15 | ||||
-rw-r--r-- | luaconf.h | 2 | ||||
-rw-r--r-- | testes/coroutine.lua | 15 |
5 files changed, 17 insertions, 26 deletions
@@ -1,7 +1,7 @@ | |||
1 | make -s -j | 1 | make -s -j |
2 | cd testes/libs; make -s | 2 | cd testes/libs; make -s |
3 | cd .. # back to directory 'testes' | 3 | cd .. # back to directory 'testes' |
4 | ulimit -S -s 1000 | 4 | ulimit -S -s 1100 |
5 | if { ../lua -W all.lua; } then | 5 | if { ../lua -W all.lua; } then |
6 | echo -e "\n\n final OK!!!!\n\n" | 6 | echo -e "\n\n final OK!!!!\n\n" |
7 | else | 7 | else |
@@ -114,13 +114,8 @@ LUA_API int lua_checkstack (lua_State *L, int n) { | |||
114 | api_check(L, n >= 0, "negative 'n'"); | 114 | api_check(L, n >= 0, "negative 'n'"); |
115 | if (L->stack_last - L->top > n) /* stack large enough? */ | 115 | if (L->stack_last - L->top > n) /* stack large enough? */ |
116 | res = 1; /* yes; check is OK */ | 116 | res = 1; /* yes; check is OK */ |
117 | else { /* no; need to grow stack */ | 117 | else /* need to grow stack */ |
118 | int inuse = cast_int(L->top - L->stack) + EXTRA_STACK; | 118 | res = luaD_growstack(L, n, 0); |
119 | if (inuse > LUAI_MAXSTACK - n) /* can grow without overflow? */ | ||
120 | res = 0; /* no */ | ||
121 | else /* try to grow stack */ | ||
122 | res = luaD_growstack(L, n, 0); | ||
123 | } | ||
124 | if (res && ci->top < L->top + n) | 119 | if (res && ci->top < L->top + n) |
125 | ci->top = L->top + n; /* adjust frame top */ | 120 | ci->top = L->top + n; /* adjust frame top */ |
126 | lua_unlock(L); | 121 | lua_unlock(L); |
@@ -227,7 +227,7 @@ int luaD_growstack (lua_State *L, int n, int raiseerror) { | |||
227 | luaD_throw(L, LUA_ERRERR); /* error inside message handler */ | 227 | luaD_throw(L, LUA_ERRERR); /* error inside message handler */ |
228 | return 0; /* if not 'raiseerror', just signal it */ | 228 | return 0; /* if not 'raiseerror', just signal it */ |
229 | } | 229 | } |
230 | else { | 230 | else if (n < LUAI_MAXSTACK) { /* avoids arithmetic overflows */ |
231 | int newsize = 2 * size; /* tentative new size */ | 231 | int newsize = 2 * size; /* tentative new size */ |
232 | int needed = cast_int(L->top - L->stack) + n; | 232 | int needed = cast_int(L->top - L->stack) + n; |
233 | if (newsize > LUAI_MAXSTACK) /* cannot cross the limit */ | 233 | if (newsize > LUAI_MAXSTACK) /* cannot cross the limit */ |
@@ -236,14 +236,13 @@ int luaD_growstack (lua_State *L, int n, int raiseerror) { | |||
236 | newsize = needed; | 236 | newsize = needed; |
237 | if (l_likely(newsize <= LUAI_MAXSTACK)) | 237 | if (l_likely(newsize <= LUAI_MAXSTACK)) |
238 | return luaD_reallocstack(L, newsize, raiseerror); | 238 | return luaD_reallocstack(L, newsize, raiseerror); |
239 | else { /* stack overflow */ | ||
240 | /* add extra size to be able to handle the error message */ | ||
241 | luaD_reallocstack(L, ERRORSTACKSIZE, raiseerror); | ||
242 | if (raiseerror) | ||
243 | luaG_runerror(L, "stack overflow"); | ||
244 | return 0; | ||
245 | } | ||
246 | } | 239 | } |
240 | /* else stack overflow */ | ||
241 | /* add extra size to be able to handle the error message */ | ||
242 | luaD_reallocstack(L, ERRORSTACKSIZE, raiseerror); | ||
243 | if (raiseerror) | ||
244 | luaG_runerror(L, "stack overflow"); | ||
245 | return 0; | ||
247 | } | 246 | } |
248 | 247 | ||
249 | 248 | ||
@@ -728,7 +728,7 @@ | |||
728 | ** CHANGE it if you need a different limit. This limit is arbitrary; | 728 | ** CHANGE it if you need a different limit. This limit is arbitrary; |
729 | ** its only purpose is to stop Lua from consuming unlimited stack | 729 | ** its only purpose is to stop Lua from consuming unlimited stack |
730 | ** space (and to reserve some numbers for pseudo-indices). | 730 | ** space (and to reserve some numbers for pseudo-indices). |
731 | ** (It must fit into max(size_t)/32.) | 731 | ** (It must fit into max(size_t)/32 and max(int)/2.) |
732 | */ | 732 | */ |
733 | #if LUAI_IS32INT | 733 | #if LUAI_IS32INT |
734 | #define LUAI_MAXSTACK 1000000 | 734 | #define LUAI_MAXSTACK 1000000 |
diff --git a/testes/coroutine.lua b/testes/coroutine.lua index 76c9d6e6..15fccc30 100644 --- a/testes/coroutine.lua +++ b/testes/coroutine.lua | |||
@@ -741,20 +741,17 @@ _X() | |||
741 | 741 | ||
742 | if not _soft then | 742 | if not _soft then |
743 | -- bug (stack overflow) | 743 | -- bug (stack overflow) |
744 | local j = 2^9 | 744 | local lim = 1000000 -- stack limit; assume 32-bit machine |
745 | local lim = 1000000 -- (C stack limit; assume 32-bit machine) | 745 | local t = {lim - 10, lim - 5, lim - 1, lim, lim + 1, lim + 5} |
746 | local t = {lim - 10, lim - 5, lim - 1, lim, lim + 1} | ||
747 | for i = 1, #t do | 746 | for i = 1, #t do |
748 | local j = t[i] | 747 | local j = t[i] |
749 | co = coroutine.create(function() | 748 | local co = coroutine.create(function() |
750 | local t = {} | 749 | return table.unpack({}, 1, j) |
751 | for i = 1, j do t[i] = i end | ||
752 | return table.unpack(t) | ||
753 | end) | 750 | end) |
754 | local r, msg = coroutine.resume(co) | 751 | local r, msg = coroutine.resume(co) |
755 | assert(not r) | 752 | -- must fail for unpacking larger than stack limit |
753 | assert(j < lim or not r) | ||
756 | end | 754 | end |
757 | co = nil | ||
758 | end | 755 | end |
759 | 756 | ||
760 | 757 | ||