diff options
Diffstat (limited to '')
| -rw-r--r-- | ldo.c | 51 | ||||
| -rw-r--r-- | ldo.h | 1 | ||||
| -rw-r--r-- | lparser.c | 12 | ||||
| -rw-r--r-- | lstate.c | 43 | ||||
| -rw-r--r-- | lstate.h | 7 | ||||
| -rw-r--r-- | ltests.h | 5 | ||||
| -rw-r--r-- | luaconf.h | 8 | ||||
| -rw-r--r-- | lvm.c | 27 | ||||
| -rw-r--r-- | testes/all.lua | 4 | ||||
| -rw-r--r-- | testes/cstack.lua | 2 | ||||
| -rw-r--r-- | testes/errors.lua | 7 |
11 files changed, 72 insertions, 95 deletions
| @@ -139,8 +139,7 @@ l_noret luaD_throw (lua_State *L, int errcode) { | |||
| 139 | 139 | ||
| 140 | 140 | ||
| 141 | int luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud) { | 141 | int luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud) { |
| 142 | global_State *g = G(L); | 142 | l_uint32 oldnCcalls = L->nCcalls; |
| 143 | l_uint32 oldnCcalls = g->Cstacklimit - (L->nCcalls + L->nci); | ||
| 144 | struct lua_longjmp lj; | 143 | struct lua_longjmp lj; |
| 145 | lj.status = LUA_OK; | 144 | lj.status = LUA_OK; |
| 146 | lj.previous = L->errorJmp; /* chain new error handler */ | 145 | lj.previous = L->errorJmp; /* chain new error handler */ |
| @@ -149,7 +148,7 @@ int luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud) { | |||
| 149 | (*f)(L, ud); | 148 | (*f)(L, ud); |
| 150 | ); | 149 | ); |
| 151 | L->errorJmp = lj.previous; /* restore old error handler */ | 150 | L->errorJmp = lj.previous; /* restore old error handler */ |
| 152 | L->nCcalls = g->Cstacklimit - oldnCcalls - L->nci; | 151 | L->nCcalls = oldnCcalls; |
| 153 | return lj.status; | 152 | return lj.status; |
| 154 | } | 153 | } |
| 155 | 154 | ||
| @@ -348,7 +347,7 @@ static StkId rethook (lua_State *L, CallInfo *ci, StkId firstres, int nres) { | |||
| 348 | 347 | ||
| 349 | /* | 348 | /* |
| 350 | ** Check whether 'func' has a '__call' metafield. If so, put it in the | 349 | ** Check whether 'func' has a '__call' metafield. If so, put it in the |
| 351 | ** stack, below original 'func', so that 'luaD_call' can call it. Raise | 350 | ** stack, below original 'func', so that 'luaD_precall' can call it. Raise |
| 352 | ** an error if there is no '__call' metafield. | 351 | ** an error if there is no '__call' metafield. |
| 353 | */ | 352 | */ |
| 354 | void luaD_tryfuncTM (lua_State *L, StkId func) { | 353 | void luaD_tryfuncTM (lua_State *L, StkId func) { |
| @@ -454,7 +453,7 @@ void luaD_pretailcall (lua_State *L, CallInfo *ci, StkId func, int narg1) { | |||
| 454 | ** When returns, all the results are on the stack, starting at the original | 453 | ** When returns, all the results are on the stack, starting at the original |
| 455 | ** function position. | 454 | ** function position. |
| 456 | */ | 455 | */ |
| 457 | void luaD_call (lua_State *L, StkId func, int nresults) { | 456 | int luaD_precall (lua_State *L, StkId func, int nresults) { |
| 458 | lua_CFunction f; | 457 | lua_CFunction f; |
| 459 | retry: | 458 | retry: |
| 460 | switch (ttypetag(s2v(func))) { | 459 | switch (ttypetag(s2v(func))) { |
| @@ -482,7 +481,7 @@ void luaD_call (lua_State *L, StkId func, int nresults) { | |||
| 482 | lua_lock(L); | 481 | lua_lock(L); |
| 483 | api_checknelems(L, n); | 482 | api_checknelems(L, n); |
| 484 | luaD_poscall(L, ci, n); | 483 | luaD_poscall(L, ci, n); |
| 485 | break; | 484 | return 1; |
| 486 | } | 485 | } |
| 487 | case LUA_VLCL: { /* Lua function */ | 486 | case LUA_VLCL: { /* Lua function */ |
| 488 | CallInfo *ci; | 487 | CallInfo *ci; |
| @@ -501,8 +500,7 @@ void luaD_call (lua_State *L, StkId func, int nresults) { | |||
| 501 | for (; narg < nfixparams; narg++) | 500 | for (; narg < nfixparams; narg++) |
| 502 | setnilvalue(s2v(L->top++)); /* complete missing arguments */ | 501 | setnilvalue(s2v(L->top++)); /* complete missing arguments */ |
| 503 | lua_assert(ci->top <= L->stack_last); | 502 | lua_assert(ci->top <= L->stack_last); |
| 504 | luaV_execute(L, ci); /* run the function */ | 503 | return 0; |
| 505 | break; | ||
| 506 | } | 504 | } |
| 507 | default: { /* not a function */ | 505 | default: { /* not a function */ |
| 508 | checkstackGCp(L, 1, func); /* space for metamethod */ | 506 | checkstackGCp(L, 1, func); /* space for metamethod */ |
| @@ -513,17 +511,32 @@ void luaD_call (lua_State *L, StkId func, int nresults) { | |||
| 513 | } | 511 | } |
| 514 | 512 | ||
| 515 | 513 | ||
| 514 | static void stackerror (lua_State *L) { | ||
| 515 | if (getCcalls(L) == LUAI_MAXCCALLS) | ||
| 516 | luaG_runerror(L, "C stack overflow"); | ||
| 517 | else if (getCcalls(L) >= (LUAI_MAXCCALLS + (LUAI_MAXCCALLS>>3))) | ||
| 518 | luaD_throw(L, LUA_ERRERR); /* error while handing stack error */ | ||
| 519 | } | ||
| 520 | |||
| 521 | |||
| 522 | void luaD_call (lua_State *L, StkId func, int nResults) { | ||
| 523 | L->nCcalls++; | ||
| 524 | if (getCcalls(L) >= LUAI_MAXCCALLS) | ||
| 525 | stackerror(L); | ||
| 526 | if (!luaD_precall(L, func, nResults)) /* is a Lua function? */ | ||
| 527 | luaV_execute(L, L->ci); /* call it */ | ||
| 528 | L->nCcalls--; | ||
| 529 | } | ||
| 530 | |||
| 531 | |||
| 532 | |||
| 516 | /* | 533 | /* |
| 517 | ** Similar to 'luaD_call', but does not allow yields during the call. | 534 | ** Similar to 'luaD_call', but does not allow yields during the call. |
| 518 | */ | 535 | */ |
| 519 | void luaD_callnoyield (lua_State *L, StkId func, int nResults) { | 536 | void luaD_callnoyield (lua_State *L, StkId func, int nResults) { |
| 520 | incXCcalls(L); | 537 | incnny(L); |
| 521 | if (getCcalls(L) <= CSTACKERR) { /* possible C stack overflow? */ | ||
| 522 | luaE_exitCcall(L); /* to compensate decrement in next call */ | ||
| 523 | luaE_enterCcall(L); /* check properly */ | ||
| 524 | } | ||
| 525 | luaD_call(L, func, nResults); | 538 | luaD_call(L, func, nResults); |
| 526 | decXCcalls(L); | 539 | decnny(L); |
| 527 | } | 540 | } |
| 528 | 541 | ||
| 529 | 542 | ||
| @@ -638,7 +651,8 @@ static void resume (lua_State *L, void *ud) { | |||
| 638 | StkId firstArg = L->top - n; /* first argument */ | 651 | StkId firstArg = L->top - n; /* first argument */ |
| 639 | CallInfo *ci = L->ci; | 652 | CallInfo *ci = L->ci; |
| 640 | if (L->status == LUA_OK) { /* starting a coroutine? */ | 653 | if (L->status == LUA_OK) { /* starting a coroutine? */ |
| 641 | luaD_call(L, firstArg - 1, LUA_MULTRET); | 654 | if (!luaD_precall(L, firstArg - 1, LUA_MULTRET)) /* Lua function? */ |
| 655 | luaV_execute(L, L->ci); /* call it */ | ||
| 642 | } | 656 | } |
| 643 | else { /* resuming from previous yield */ | 657 | else { /* resuming from previous yield */ |
| 644 | lua_assert(L->status == LUA_YIELD); | 658 | lua_assert(L->status == LUA_YIELD); |
| @@ -670,11 +684,8 @@ LUA_API int lua_resume (lua_State *L, lua_State *from, int nargs, | |||
| 670 | } | 684 | } |
| 671 | else if (L->status != LUA_YIELD) /* ended with errors? */ | 685 | else if (L->status != LUA_YIELD) /* ended with errors? */ |
| 672 | return resume_error(L, "cannot resume dead coroutine", nargs); | 686 | return resume_error(L, "cannot resume dead coroutine", nargs); |
| 673 | if (from == NULL) | 687 | L->nCcalls = (from) ? getCcalls(from) + 1 : 1; |
| 674 | L->nCcalls = CSTACKTHREAD; | 688 | if (getCcalls(L) >= LUAI_MAXCCALLS) |
| 675 | else /* correct 'nCcalls' for this thread */ | ||
| 676 | L->nCcalls = getCcalls(from) - L->nci - CSTACKCF; | ||
| 677 | if (L->nCcalls <= CSTACKERR) | ||
| 678 | return resume_error(L, "C stack overflow", nargs); | 689 | return resume_error(L, "C stack overflow", nargs); |
| 679 | luai_userstateresume(L, nargs); | 690 | luai_userstateresume(L, nargs); |
| 680 | api_checknelems(L, (L->status == LUA_OK) ? nargs + 1 : nargs); | 691 | api_checknelems(L, (L->status == LUA_OK) ? nargs + 1 : nargs); |
| @@ -59,6 +59,7 @@ LUAI_FUNC void luaD_hook (lua_State *L, int event, int line, | |||
| 59 | int fTransfer, int nTransfer); | 59 | int fTransfer, int nTransfer); |
| 60 | LUAI_FUNC void luaD_hookcall (lua_State *L, CallInfo *ci); | 60 | LUAI_FUNC void luaD_hookcall (lua_State *L, CallInfo *ci); |
| 61 | LUAI_FUNC void luaD_pretailcall (lua_State *L, CallInfo *ci, StkId func, int n); | 61 | LUAI_FUNC void luaD_pretailcall (lua_State *L, CallInfo *ci, StkId func, int n); |
| 62 | LUAI_FUNC int luaD_precall (lua_State *L, StkId func, int nResults); | ||
| 62 | LUAI_FUNC void luaD_call (lua_State *L, StkId func, int nResults); | 63 | LUAI_FUNC void luaD_call (lua_State *L, StkId func, int nResults); |
| 63 | LUAI_FUNC void luaD_callnoyield (lua_State *L, StkId func, int nResults); | 64 | LUAI_FUNC void luaD_callnoyield (lua_State *L, StkId func, int nResults); |
| 64 | LUAI_FUNC void luaD_tryfuncTM (lua_State *L, StkId func); | 65 | LUAI_FUNC void luaD_tryfuncTM (lua_State *L, StkId func); |
| @@ -489,12 +489,14 @@ static void adjust_assign (LexState *ls, int nvars, int nexps, expdesc *e) { | |||
| 489 | } | 489 | } |
| 490 | 490 | ||
| 491 | 491 | ||
| 492 | /* | 492 | static void enterlevel (LexState *ls) { |
| 493 | ** Macros to limit the maximum recursion depth while parsing | 493 | lua_State *L = ls->L; |
| 494 | */ | 494 | L->nCcalls++; |
| 495 | #define enterlevel(ls) luaE_enterCcall((ls)->L) | 495 | checklimit(ls->fs, getCcalls(L), LUAI_MAXCCALLS, "C levels"); |
| 496 | } | ||
| 497 | |||
| 496 | 498 | ||
| 497 | #define leavelevel(ls) luaE_exitCcall((ls)->L) | 499 | #define leavelevel(ls) ((ls)->L->nCcalls--) |
| 498 | 500 | ||
| 499 | 501 | ||
| 500 | /* | 502 | /* |
| @@ -119,44 +119,9 @@ LUA_API int lua_setcstacklimit (lua_State *L, unsigned int limit) { | |||
| 119 | } | 119 | } |
| 120 | 120 | ||
| 121 | 121 | ||
| 122 | /* | ||
| 123 | ** Decrement count of "C calls" and check for overflows. In case of | ||
| 124 | ** a stack overflow, check appropriate error ("regular" overflow or | ||
| 125 | ** overflow while handling stack overflow). If 'nCcalls' is smaller | ||
| 126 | ** than CSTACKERR but larger than CSTACKMARK, it means it has just | ||
| 127 | ** entered the "overflow zone", so the function raises an overflow | ||
| 128 | ** error. If 'nCcalls' is smaller than CSTACKMARK (which means it is | ||
| 129 | ** already handling an overflow) but larger than CSTACKERRMARK, does | ||
| 130 | ** not report an error (to allow message handling to work). Otherwise, | ||
| 131 | ** report a stack overflow while handling a stack overflow (probably | ||
| 132 | ** caused by a repeating error in the message handling function). | ||
| 133 | */ | ||
| 134 | |||
| 135 | void luaE_enterCcall (lua_State *L) { | ||
| 136 | int ncalls = getCcalls(L); | ||
| 137 | L->nCcalls--; | ||
| 138 | if (ncalls <= CSTACKERR) { /* possible overflow? */ | ||
| 139 | luaE_freeCI(L); /* release unused CIs */ | ||
| 140 | ncalls = getCcalls(L); /* update call count */ | ||
| 141 | if (ncalls <= CSTACKERR) { /* still overflow? */ | ||
| 142 | if (ncalls <= CSTACKERRMARK) /* below error-handling zone? */ | ||
| 143 | luaD_throw(L, LUA_ERRERR); /* error while handling stack error */ | ||
| 144 | else if (ncalls >= CSTACKMARK) { | ||
| 145 | /* not in error-handling zone; raise the error now */ | ||
| 146 | L->nCcalls = (CSTACKMARK - 1); /* enter error-handling zone */ | ||
| 147 | luaG_runerror(L, "C stack overflow"); | ||
| 148 | } | ||
| 149 | /* else stack is in the error-handling zone; | ||
| 150 | allow message handler to work */ | ||
| 151 | } | ||
| 152 | } | ||
| 153 | } | ||
| 154 | |||
| 155 | |||
| 156 | CallInfo *luaE_extendCI (lua_State *L) { | 122 | CallInfo *luaE_extendCI (lua_State *L) { |
| 157 | CallInfo *ci; | 123 | CallInfo *ci; |
| 158 | lua_assert(L->ci->next == NULL); | 124 | lua_assert(L->ci->next == NULL); |
| 159 | luaE_enterCcall(L); | ||
| 160 | ci = luaM_new(L, CallInfo); | 125 | ci = luaM_new(L, CallInfo); |
| 161 | lua_assert(L->ci->next == NULL); | 126 | lua_assert(L->ci->next == NULL); |
| 162 | L->ci->next = ci; | 127 | L->ci->next = ci; |
| @@ -175,13 +140,11 @@ void luaE_freeCI (lua_State *L) { | |||
| 175 | CallInfo *ci = L->ci; | 140 | CallInfo *ci = L->ci; |
| 176 | CallInfo *next = ci->next; | 141 | CallInfo *next = ci->next; |
| 177 | ci->next = NULL; | 142 | ci->next = NULL; |
| 178 | L->nCcalls += L->nci; /* add removed elements back to 'nCcalls' */ | ||
| 179 | while ((ci = next) != NULL) { | 143 | while ((ci = next) != NULL) { |
| 180 | next = ci->next; | 144 | next = ci->next; |
| 181 | luaM_free(L, ci); | 145 | luaM_free(L, ci); |
| 182 | L->nci--; | 146 | L->nci--; |
| 183 | } | 147 | } |
| 184 | L->nCcalls -= L->nci; /* adjust result */ | ||
| 185 | } | 148 | } |
| 186 | 149 | ||
| 187 | 150 | ||
| @@ -194,7 +157,6 @@ void luaE_shrinkCI (lua_State *L) { | |||
| 194 | CallInfo *next; | 157 | CallInfo *next; |
| 195 | if (ci == NULL) | 158 | if (ci == NULL) |
| 196 | return; /* no extra elements */ | 159 | return; /* no extra elements */ |
| 197 | L->nCcalls += L->nci; /* add removed elements back to 'nCcalls' */ | ||
| 198 | while ((next = ci->next) != NULL) { /* two extra elements? */ | 160 | while ((next = ci->next) != NULL) { /* two extra elements? */ |
| 199 | CallInfo *next2 = next->next; /* next's next */ | 161 | CallInfo *next2 = next->next; /* next's next */ |
| 200 | ci->next = next2; /* remove next from the list */ | 162 | ci->next = next2; /* remove next from the list */ |
| @@ -207,7 +169,6 @@ void luaE_shrinkCI (lua_State *L) { | |||
| 207 | ci = next2; /* continue */ | 169 | ci = next2; /* continue */ |
| 208 | } | 170 | } |
| 209 | } | 171 | } |
| 210 | L->nCcalls -= L->nci; /* adjust result */ | ||
| 211 | } | 172 | } |
| 212 | 173 | ||
| 213 | 174 | ||
| @@ -335,7 +296,7 @@ LUA_API lua_State *lua_newthread (lua_State *L) { | |||
| 335 | setthvalue2s(L, L->top, L1); | 296 | setthvalue2s(L, L->top, L1); |
| 336 | api_incr_top(L); | 297 | api_incr_top(L); |
| 337 | preinit_thread(L1, g); | 298 | preinit_thread(L1, g); |
| 338 | L1->nCcalls = getCcalls(L); | 299 | L1->nCcalls = 0; |
| 339 | L1->hookmask = L->hookmask; | 300 | L1->hookmask = L->hookmask; |
| 340 | L1->basehookcount = L->basehookcount; | 301 | L1->basehookcount = L->basehookcount; |
| 341 | L1->hook = L->hook; | 302 | L1->hook = L->hook; |
| @@ -396,7 +357,7 @@ LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) { | |||
| 396 | preinit_thread(L, g); | 357 | preinit_thread(L, g); |
| 397 | g->allgc = obj2gco(L); /* by now, only object is the main thread */ | 358 | g->allgc = obj2gco(L); /* by now, only object is the main thread */ |
| 398 | L->next = NULL; | 359 | L->next = NULL; |
| 399 | g->Cstacklimit = L->nCcalls = LUAI_MAXCSTACK + CSTACKERR; | 360 | g->Cstacklimit = L->nCcalls = 0; |
| 400 | incnny(L); /* main thread is always non yieldable */ | 361 | incnny(L); /* main thread is always non yieldable */ |
| 401 | g->frealloc = f; | 362 | g->frealloc = f; |
| 402 | g->ud = ud; | 363 | g->ud = ud; |
| @@ -144,12 +144,6 @@ | |||
| 144 | /* Decrement the number of non-yieldable calls */ | 144 | /* Decrement the number of non-yieldable calls */ |
| 145 | #define decnny(L) ((L)->nCcalls -= 0x10000) | 145 | #define decnny(L) ((L)->nCcalls -= 0x10000) |
| 146 | 146 | ||
| 147 | /* Increment the number of non-yieldable calls and decrement nCcalls */ | ||
| 148 | #define incXCcalls(L) ((L)->nCcalls += 0x10000 - CSTACKCF) | ||
| 149 | |||
| 150 | /* Decrement the number of non-yieldable calls and increment nCcalls */ | ||
| 151 | #define decXCcalls(L) ((L)->nCcalls -= 0x10000 - CSTACKCF) | ||
| 152 | |||
| 153 | 147 | ||
| 154 | 148 | ||
| 155 | 149 | ||
| @@ -389,7 +383,6 @@ LUAI_FUNC void luaE_freethread (lua_State *L, lua_State *L1); | |||
| 389 | LUAI_FUNC CallInfo *luaE_extendCI (lua_State *L); | 383 | LUAI_FUNC CallInfo *luaE_extendCI (lua_State *L); |
| 390 | LUAI_FUNC void luaE_freeCI (lua_State *L); | 384 | LUAI_FUNC void luaE_freeCI (lua_State *L); |
| 391 | LUAI_FUNC void luaE_shrinkCI (lua_State *L); | 385 | LUAI_FUNC void luaE_shrinkCI (lua_State *L); |
| 392 | LUAI_FUNC void luaE_enterCcall (lua_State *L); | ||
| 393 | LUAI_FUNC void luaE_warning (lua_State *L, const char *msg, int tocont); | 386 | LUAI_FUNC void luaE_warning (lua_State *L, const char *msg, int tocont); |
| 394 | LUAI_FUNC void luaE_warnerror (lua_State *L, const char *where); | 387 | LUAI_FUNC void luaE_warnerror (lua_State *L, const char *where); |
| 395 | 388 | ||
| @@ -23,11 +23,6 @@ | |||
| 23 | #define LUAI_ASSERT | 23 | #define LUAI_ASSERT |
| 24 | 24 | ||
| 25 | 25 | ||
| 26 | |||
| 27 | /* compiled with -O0, Lua uses a lot of C stack space... */ | ||
| 28 | #undef LUAI_MAXCSTACK | ||
| 29 | #define LUAI_MAXCSTACK 400 | ||
| 30 | |||
| 31 | /* to avoid warnings, and to make sure value is really unused */ | 26 | /* to avoid warnings, and to make sure value is really unused */ |
| 32 | #define UNUSED(x) (x=0, (void)(x)) | 27 | #define UNUSED(x) (x=0, (void)(x)) |
| 33 | 28 | ||
| @@ -36,8 +36,8 @@ | |||
| 36 | ** ===================================================================== | 36 | ** ===================================================================== |
| 37 | */ | 37 | */ |
| 38 | 38 | ||
| 39 | /* | 39 | /* >>> move back to llimits.h |
| 40 | @@ LUAI_MAXCSTACK defines the maximum depth for nested calls and | 40 | @@ LUAI_MAXCCALLS defines the maximum depth for nested calls and |
| 41 | ** also limits the maximum depth of other recursive algorithms in | 41 | ** also limits the maximum depth of other recursive algorithms in |
| 42 | ** the implementation, such as syntactic analysis. A value too | 42 | ** the implementation, such as syntactic analysis. A value too |
| 43 | ** large may allow the interpreter to crash (C-stack overflow). | 43 | ** large may allow the interpreter to crash (C-stack overflow). |
| @@ -46,8 +46,8 @@ | |||
| 46 | ** The test file 'cstack.lua' may help finding a good limit. | 46 | ** The test file 'cstack.lua' may help finding a good limit. |
| 47 | ** (It will crash with a limit too high.) | 47 | ** (It will crash with a limit too high.) |
| 48 | */ | 48 | */ |
| 49 | #if !defined(LUAI_MAXCSTACK) | 49 | #if !defined(LUAI_MAXCCALLS) |
| 50 | #define LUAI_MAXCSTACK 2000 | 50 | #define LUAI_MAXCCALLS 200 |
| 51 | #endif | 51 | #endif |
| 52 | 52 | ||
| 53 | 53 | ||
| @@ -229,7 +229,7 @@ static int forprep (lua_State *L, StkId ra) { | |||
| 229 | count /= l_castS2U(-(step + 1)) + 1u; | 229 | count /= l_castS2U(-(step + 1)) + 1u; |
| 230 | } | 230 | } |
| 231 | /* store the counter in place of the limit (which won't be | 231 | /* store the counter in place of the limit (which won't be |
| 232 | needed anymore */ | 232 | needed anymore) */ |
| 233 | setivalue(plimit, l_castU2S(count)); | 233 | setivalue(plimit, l_castU2S(count)); |
| 234 | } | 234 | } |
| 235 | } | 235 | } |
| @@ -1124,6 +1124,7 @@ void luaV_finishOp (lua_State *L) { | |||
| 1124 | 1124 | ||
| 1125 | 1125 | ||
| 1126 | void luaV_execute (lua_State *L, CallInfo *ci) { | 1126 | void luaV_execute (lua_State *L, CallInfo *ci) { |
| 1127 | const CallInfo *origci = ci; | ||
| 1127 | LClosure *cl; | 1128 | LClosure *cl; |
| 1128 | TValue *k; | 1129 | TValue *k; |
| 1129 | StkId base; | 1130 | StkId base; |
| @@ -1611,7 +1612,13 @@ void luaV_execute (lua_State *L, CallInfo *ci) { | |||
| 1611 | if (b != 0) /* fixed number of arguments? */ | 1612 | if (b != 0) /* fixed number of arguments? */ |
| 1612 | L->top = ra + b; /* top signals number of arguments */ | 1613 | L->top = ra + b; /* top signals number of arguments */ |
| 1613 | /* else previous instruction set top */ | 1614 | /* else previous instruction set top */ |
| 1614 | ProtectNT(luaD_call(L, ra, nresults)); | 1615 | savepc(L); /* in case of errors */ |
| 1616 | if (luaD_precall(L, ra, nresults)) | ||
| 1617 | updatetrap(ci); /* C call; nothing else to be done */ | ||
| 1618 | else { /* Lua call: run function in this same invocation */ | ||
| 1619 | ci = L->ci; | ||
| 1620 | goto tailcall; | ||
| 1621 | } | ||
| 1615 | vmbreak; | 1622 | vmbreak; |
| 1616 | } | 1623 | } |
| 1617 | vmcase(OP_TAILCALL) { | 1624 | vmcase(OP_TAILCALL) { |
| @@ -1637,12 +1644,12 @@ void luaV_execute (lua_State *L, CallInfo *ci) { | |||
| 1637 | checkstackGCp(L, 1, ra); | 1644 | checkstackGCp(L, 1, ra); |
| 1638 | } | 1645 | } |
| 1639 | if (!ttisLclosure(s2v(ra))) { /* C function? */ | 1646 | if (!ttisLclosure(s2v(ra))) { /* C function? */ |
| 1640 | luaD_call(L, ra, LUA_MULTRET); /* call it */ | 1647 | luaD_precall(L, ra, LUA_MULTRET); /* call it */ |
| 1641 | updatetrap(ci); | 1648 | updatetrap(ci); |
| 1642 | updatestack(ci); /* stack may have been relocated */ | 1649 | updatestack(ci); /* stack may have been relocated */ |
| 1643 | ci->func -= delta; | 1650 | ci->func -= delta; |
| 1644 | luaD_poscall(L, ci, cast_int(L->top - ra)); | 1651 | luaD_poscall(L, ci, cast_int(L->top - ra)); |
| 1645 | return; | 1652 | goto ret; |
| 1646 | } | 1653 | } |
| 1647 | ci->func -= delta; | 1654 | ci->func -= delta; |
| 1648 | luaD_pretailcall(L, ci, ra, b); /* prepare call frame */ | 1655 | luaD_pretailcall(L, ci, ra, b); /* prepare call frame */ |
| @@ -1665,7 +1672,7 @@ void luaV_execute (lua_State *L, CallInfo *ci) { | |||
| 1665 | ci->func -= ci->u.l.nextraargs + nparams1; | 1672 | ci->func -= ci->u.l.nextraargs + nparams1; |
| 1666 | L->top = ra + n; /* set call for 'luaD_poscall' */ | 1673 | L->top = ra + n; /* set call for 'luaD_poscall' */ |
| 1667 | luaD_poscall(L, ci, n); | 1674 | luaD_poscall(L, ci, n); |
| 1668 | return; | 1675 | goto ret; |
| 1669 | } | 1676 | } |
| 1670 | vmcase(OP_RETURN0) { | 1677 | vmcase(OP_RETURN0) { |
| 1671 | if (L->hookmask) { | 1678 | if (L->hookmask) { |
| @@ -1679,7 +1686,7 @@ void luaV_execute (lua_State *L, CallInfo *ci) { | |||
| 1679 | while (nres-- > 0) | 1686 | while (nres-- > 0) |
| 1680 | setnilvalue(s2v(L->top++)); /* all results are nil */ | 1687 | setnilvalue(s2v(L->top++)); /* all results are nil */ |
| 1681 | } | 1688 | } |
| 1682 | return; | 1689 | goto ret; |
| 1683 | } | 1690 | } |
| 1684 | vmcase(OP_RETURN1) { | 1691 | vmcase(OP_RETURN1) { |
| 1685 | if (L->hookmask) { | 1692 | if (L->hookmask) { |
| @@ -1698,7 +1705,13 @@ void luaV_execute (lua_State *L, CallInfo *ci) { | |||
| 1698 | setnilvalue(s2v(L->top++)); | 1705 | setnilvalue(s2v(L->top++)); |
| 1699 | } | 1706 | } |
| 1700 | } | 1707 | } |
| 1701 | return; | 1708 | ret: |
| 1709 | if (ci == origci) | ||
| 1710 | return; | ||
| 1711 | else { | ||
| 1712 | ci = ci->previous; | ||
| 1713 | goto tailcall; | ||
| 1714 | } | ||
| 1702 | } | 1715 | } |
| 1703 | vmcase(OP_FORLOOP) { | 1716 | vmcase(OP_FORLOOP) { |
| 1704 | if (ttisinteger(s2v(ra + 2))) { /* integer loop? */ | 1717 | if (ttisinteger(s2v(ra + 2))) { /* integer loop? */ |
diff --git a/testes/all.lua b/testes/all.lua index db074dd8..a4feeec1 100644 --- a/testes/all.lua +++ b/testes/all.lua | |||
| @@ -127,8 +127,8 @@ else | |||
| 127 | end | 127 | end |
| 128 | 128 | ||
| 129 | Cstacklevel = function () | 129 | Cstacklevel = function () |
| 130 | local _, _, ncalls, nci = T.stacklevel() | 130 | local _, _, ncalls = T.stacklevel() |
| 131 | return ncalls + nci -- number of free slots in the C stack | 131 | return ncalls -- number of C calls |
| 132 | end | 132 | end |
| 133 | end | 133 | end |
| 134 | 134 | ||
diff --git a/testes/cstack.lua b/testes/cstack.lua index 4e37b988..c1177f3b 100644 --- a/testes/cstack.lua +++ b/testes/cstack.lua | |||
| @@ -1,6 +1,8 @@ | |||
| 1 | -- $Id: testes/cstack.lua $ | 1 | -- $Id: testes/cstack.lua $ |
| 2 | -- See Copyright Notice in file all.lua | 2 | -- See Copyright Notice in file all.lua |
| 3 | 3 | ||
| 4 | do return end | ||
| 5 | |||
| 4 | local debug = require "debug" | 6 | local debug = require "debug" |
| 5 | 7 | ||
| 6 | print"testing C-stack overflow detection" | 8 | print"testing C-stack overflow detection" |
diff --git a/testes/errors.lua b/testes/errors.lua index f9623b1d..88918df7 100644 --- a/testes/errors.lua +++ b/testes/errors.lua | |||
| @@ -530,10 +530,9 @@ local function testrep (init, rep, close, repc, finalresult) | |||
| 530 | if (finalresult) then | 530 | if (finalresult) then |
| 531 | assert(res() == finalresult) | 531 | assert(res() == finalresult) |
| 532 | end | 532 | end |
| 533 | s = init .. string.rep(rep, 10000) | 533 | s = init .. string.rep(rep, 500) |
| 534 | local res, msg = load(s) -- 10000 levels not ok | 534 | local res, msg = load(s) -- 500 levels not ok |
| 535 | assert(not res and (string.find(msg, "too many registers") or | 535 | assert(not res and string.find(msg, "too many")) |
| 536 | string.find(msg, "stack overflow"))) | ||
| 537 | end | 536 | end |
| 538 | 537 | ||
| 539 | testrep("local a; a", ",a", "= 1", ",1") -- multiple assignment | 538 | testrep("local a; a", ",a", "= 1", ",1") -- multiple assignment |
