diff options
| -rw-r--r-- | ldo.c | 7 | ||||
| -rw-r--r-- | ldo.h | 7 | ||||
| -rw-r--r-- | lobject.c | 34 | ||||
| -rw-r--r-- | lobject.h | 2 | ||||
| -rw-r--r-- | testes/calls.lua | 10 |
5 files changed, 47 insertions, 13 deletions
| @@ -602,12 +602,17 @@ CallInfo *luaD_precall (lua_State *L, StkId func, int nresults) { | |||
| 602 | ** Call a function (C or Lua) through C. 'inc' can be 1 (increment | 602 | ** Call a function (C or Lua) through C. 'inc' can be 1 (increment |
| 603 | ** number of recursive invocations in the C stack) or nyci (the same | 603 | ** number of recursive invocations in the C stack) or nyci (the same |
| 604 | ** plus increment number of non-yieldable calls). | 604 | ** plus increment number of non-yieldable calls). |
| 605 | ** This function can be called with some use of EXTRA_STACK, so it should | ||
| 606 | ** check the stack before doing anything else. 'luaD_precall' already | ||
| 607 | ** does that. | ||
| 605 | */ | 608 | */ |
| 606 | l_sinline void ccall (lua_State *L, StkId func, int nResults, int inc) { | 609 | l_sinline void ccall (lua_State *L, StkId func, int nResults, int inc) { |
| 607 | CallInfo *ci; | 610 | CallInfo *ci; |
| 608 | L->nCcalls += inc; | 611 | L->nCcalls += inc; |
| 609 | if (l_unlikely(getCcalls(L) >= LUAI_MAXCCALLS)) | 612 | if (l_unlikely(getCcalls(L) >= LUAI_MAXCCALLS)) { |
| 613 | checkstackp(L, 0, func); /* free any use of EXTRA_STACK */ | ||
| 610 | luaE_checkcstack(L); | 614 | luaE_checkcstack(L); |
| 615 | } | ||
| 611 | if ((ci = luaD_precall(L, func, nResults)) != NULL) { /* Lua function? */ | 616 | if ((ci = luaD_precall(L, func, nResults)) != NULL) { /* Lua function? */ |
| 612 | ci->callstatus = CIST_FRESH; /* mark that it is a "fresh" execute */ | 617 | ci->callstatus = CIST_FRESH; /* mark that it is a "fresh" execute */ |
| 613 | luaV_execute(L, ci); /* call it */ | 618 | luaV_execute(L, ci); /* call it */ |
| @@ -37,6 +37,13 @@ | |||
| 37 | 37 | ||
| 38 | 38 | ||
| 39 | /* macro to check stack size, preserving 'p' */ | 39 | /* macro to check stack size, preserving 'p' */ |
| 40 | #define checkstackp(L,n,p) \ | ||
| 41 | luaD_checkstackaux(L, n, \ | ||
| 42 | ptrdiff_t t__ = savestack(L, p), /* save 'p' */ \ | ||
| 43 | p = restorestack(L, t__)) /* 'pos' part: restore 'p' */ | ||
| 44 | |||
| 45 | |||
| 46 | /* macro to check stack size and GC, preserving 'p' */ | ||
| 40 | #define checkstackGCp(L,n,p) \ | 47 | #define checkstackGCp(L,n,p) \ |
| 41 | luaD_checkstackaux(L, n, \ | 48 | luaD_checkstackaux(L, n, \ |
| 42 | ptrdiff_t t__ = savestack(L, p); /* save 'p' */ \ | 49 | ptrdiff_t t__ = savestack(L, p); /* save 'p' */ \ |
| @@ -386,29 +386,39 @@ void luaO_tostring (lua_State *L, TValue *obj) { | |||
| 386 | ** =================================================================== | 386 | ** =================================================================== |
| 387 | */ | 387 | */ |
| 388 | 388 | ||
| 389 | /* size for buffer space used by 'luaO_pushvfstring' */ | 389 | /* |
| 390 | #define BUFVFS 200 | 390 | ** Size for buffer space used by 'luaO_pushvfstring'. It should be |
| 391 | ** (LUA_IDSIZE + MAXNUMBER2STR) + a minimal space for basic messages, | ||
| 392 | ** so that 'luaG_addinfo' can work directly on the buffer. | ||
| 393 | */ | ||
| 394 | #define BUFVFS (LUA_IDSIZE + MAXNUMBER2STR + 95) | ||
| 391 | 395 | ||
| 392 | /* buffer used by 'luaO_pushvfstring' */ | 396 | /* buffer used by 'luaO_pushvfstring' */ |
| 393 | typedef struct BuffFS { | 397 | typedef struct BuffFS { |
| 394 | lua_State *L; | 398 | lua_State *L; |
| 395 | int pushed; /* number of string pieces already on the stack */ | 399 | int pushed; /* true if there is a part of the result on the stack */ |
| 396 | int blen; /* length of partial string in 'space' */ | 400 | int blen; /* length of partial string in 'space' */ |
| 397 | char space[BUFVFS]; /* holds last part of the result */ | 401 | char space[BUFVFS]; /* holds last part of the result */ |
| 398 | } BuffFS; | 402 | } BuffFS; |
| 399 | 403 | ||
| 400 | 404 | ||
| 401 | /* | 405 | /* |
| 402 | ** Push given string to the stack, as part of the buffer, and | 406 | ** Push given string to the stack, as part of the result, and |
| 403 | ** join the partial strings in the stack into one. | 407 | ** join it to previous partial result if there is one. |
| 408 | ** It may call 'luaV_concat' while using one slot from EXTRA_STACK. | ||
| 409 | ** This call cannot invoke metamethods, as both operands must be | ||
| 410 | ** strings. It can, however, raise an error if the result is too | ||
| 411 | ** long. In that case, 'luaV_concat' frees the extra slot before | ||
| 412 | ** raising the error. | ||
| 404 | */ | 413 | */ |
| 405 | static void pushstr (BuffFS *buff, const char *str, size_t l) { | 414 | static void pushstr (BuffFS *buff, const char *str, size_t lstr) { |
| 406 | lua_State *L = buff->L; | 415 | lua_State *L = buff->L; |
| 407 | setsvalue2s(L, L->top, luaS_newlstr(L, str, l)); | 416 | setsvalue2s(L, L->top, luaS_newlstr(L, str, lstr)); |
| 408 | L->top++; /* may use one extra slot */ | 417 | L->top++; /* may use one slot from EXTRA_STACK */ |
| 409 | buff->pushed++; | 418 | if (!buff->pushed) /* no previous string on the stack? */ |
| 410 | luaV_concat(L, buff->pushed); /* join partial results into one */ | 419 | buff->pushed = 1; /* now there is one */ |
| 411 | buff->pushed = 1; | 420 | else /* join previous string with new one */ |
| 421 | luaV_concat(L, 2); | ||
| 412 | } | 422 | } |
| 413 | 423 | ||
| 414 | 424 | ||
| @@ -454,7 +464,7 @@ static void addstr2buff (BuffFS *buff, const char *str, size_t slen) { | |||
| 454 | 464 | ||
| 455 | 465 | ||
| 456 | /* | 466 | /* |
| 457 | ** Add a number to the buffer. | 467 | ** Add a numeral to the buffer. |
| 458 | */ | 468 | */ |
| 459 | static void addnum2buff (BuffFS *buff, TValue *num) { | 469 | static void addnum2buff (BuffFS *buff, TValue *num) { |
| 460 | char *numbuff = getbuff(buff, MAXNUMBER2STR); | 470 | char *numbuff = getbuff(buff, MAXNUMBER2STR); |
| @@ -52,6 +52,8 @@ typedef union Value { | |||
| 52 | lua_CFunction f; /* light C functions */ | 52 | lua_CFunction f; /* light C functions */ |
| 53 | lua_Integer i; /* integer numbers */ | 53 | lua_Integer i; /* integer numbers */ |
| 54 | lua_Number n; /* float numbers */ | 54 | lua_Number n; /* float numbers */ |
| 55 | /* not used, but may avoid warnings for uninitialized value */ | ||
| 56 | lu_byte ub; | ||
| 55 | } Value; | 57 | } Value; |
| 56 | 58 | ||
| 57 | 59 | ||
diff --git a/testes/calls.lua b/testes/calls.lua index ff72d8f6..ee8cce73 100644 --- a/testes/calls.lua +++ b/testes/calls.lua | |||
| @@ -151,6 +151,16 @@ do -- tail calls x varargs | |||
| 151 | end | 151 | end |
| 152 | 152 | ||
| 153 | 153 | ||
| 154 | do -- C-stack overflow while handling C-stack overflow | ||
| 155 | local function loop () | ||
| 156 | assert(pcall(loop)) | ||
| 157 | end | ||
| 158 | |||
| 159 | local err, msg = xpcall(loop, loop) | ||
| 160 | assert(not err and string.find(msg, "error")) | ||
| 161 | end | ||
| 162 | |||
| 163 | |||
| 154 | 164 | ||
| 155 | do -- tail calls x chain of __call | 165 | do -- tail calls x chain of __call |
| 156 | local n = 10000 -- depth | 166 | local n = 10000 -- depth |
