diff options
Diffstat (limited to 'lstate.c')
| -rw-r--r-- | lstate.c | 49 |
1 files changed, 33 insertions, 16 deletions
| @@ -99,24 +99,42 @@ void luaE_setdebt (global_State *g, l_mem debt) { | |||
| 99 | /* | 99 | /* |
| 100 | ** Increment count of "C calls" and check for overflows. In case of | 100 | ** Increment count of "C calls" and check for overflows. In case of |
| 101 | ** a stack overflow, check appropriate error ("regular" overflow or | 101 | ** a stack overflow, check appropriate error ("regular" overflow or |
| 102 | ** overflow while handling stack overflow). If 'nCalls' is larger than | 102 | ** overflow while handling stack overflow). |
| 103 | ** LUAI_MAXCCALLS (which means it is handling a "regular" overflow) but | 103 | ** If 'nCcalls' is larger than LUAI_MAXCCALLS but smaller than |
| 104 | ** smaller than 9/8 of LUAI_MAXCCALLS, does not report an error (to | 104 | ** LUAI_MAXCCALLS + CSTACKCF (plus 2 to avoid by-one errors), it means |
| 105 | ** allow overflow handling to work) | 105 | ** it has just entered the "overflow zone", so the function raises an |
| 106 | ** overflow error. | ||
| 107 | ** If 'nCcalls' is larger than LUAI_MAXCCALLS + CSTACKCF + 2 | ||
| 108 | ** (which means it is already handling an overflow) but smaller than | ||
| 109 | ** 9/8 of LUAI_MAXCCALLS, does not report an error (to allow message | ||
| 110 | ** handling to work). | ||
| 111 | ** Otherwise, report a stack overflow while handling a stack overflow | ||
| 112 | ** (probably caused by a repeating error in the message handling | ||
| 113 | ** function). | ||
| 106 | */ | 114 | */ |
| 107 | void luaE_incCcalls (lua_State *L) { | 115 | void luaE_enterCcall (lua_State *L) { |
| 108 | if (++L->nCcalls >= LUAI_MAXCCALLS) { | 116 | int ncalls = getCcalls(L); |
| 109 | if (L->nCcalls == LUAI_MAXCCALLS) | 117 | L->nCcalls++; |
| 110 | luaG_runerror(L, "C stack overflow"); | 118 | if (ncalls >= LUAI_MAXCCALLS) { /* possible overflow? */ |
| 111 | else if (L->nCcalls >= (LUAI_MAXCCALLS + (LUAI_MAXCCALLS>>3))) | 119 | luaE_freeCI(L); /* release unused CIs */ |
| 112 | luaD_throw(L, LUA_ERRERR); /* error while handing stack error */ | 120 | ncalls = getCcalls(L); /* update call count */ |
| 121 | if (ncalls >= LUAI_MAXCCALLS) { /* still overflow? */ | ||
| 122 | if (ncalls <= LUAI_MAXCCALLS + CSTACKCF + 2) { | ||
| 123 | /* no error before increments; raise the error now */ | ||
| 124 | L->nCcalls += (CSTACKCF + 4); /* avoid raising it again */ | ||
| 125 | luaG_runerror(L, "C stack overflow"); | ||
| 126 | } | ||
| 127 | else if (ncalls >= (LUAI_MAXCCALLS + (LUAI_MAXCCALLS >> 3))) | ||
| 128 | luaD_throw(L, LUA_ERRERR); /* error while handling stack error */ | ||
| 129 | } | ||
| 113 | } | 130 | } |
| 114 | } | 131 | } |
| 115 | 132 | ||
| 116 | 133 | ||
| 117 | CallInfo *luaE_extendCI (lua_State *L) { | 134 | CallInfo *luaE_extendCI (lua_State *L) { |
| 118 | CallInfo *ci; | 135 | CallInfo *ci; |
| 119 | luaE_incCcalls(L); | 136 | lua_assert(L->ci->next == NULL); |
| 137 | luaE_enterCcall(L); | ||
| 120 | ci = luaM_new(L, CallInfo); | 138 | ci = luaM_new(L, CallInfo); |
| 121 | lua_assert(L->ci->next == NULL); | 139 | lua_assert(L->ci->next == NULL); |
| 122 | L->ci->next = ci; | 140 | L->ci->next = ci; |
| @@ -135,13 +153,13 @@ void luaE_freeCI (lua_State *L) { | |||
| 135 | CallInfo *ci = L->ci; | 153 | CallInfo *ci = L->ci; |
| 136 | CallInfo *next = ci->next; | 154 | CallInfo *next = ci->next; |
| 137 | ci->next = NULL; | 155 | ci->next = NULL; |
| 138 | L->nCcalls -= L->nci; /* to subtract removed elements from 'nCcalls' */ | 156 | L->nCcalls -= L->nci; /* subtract removed elements from 'nCcalls' */ |
| 139 | while ((ci = next) != NULL) { | 157 | while ((ci = next) != NULL) { |
| 140 | next = ci->next; | 158 | next = ci->next; |
| 141 | luaM_free(L, ci); | 159 | luaM_free(L, ci); |
| 142 | L->nci--; | 160 | L->nci--; |
| 143 | } | 161 | } |
| 144 | L->nCcalls += L->nci; /* to subtract removed elements from 'nCcalls' */ | 162 | L->nCcalls += L->nci; /* adjust result */ |
| 145 | } | 163 | } |
| 146 | 164 | ||
| 147 | 165 | ||
| @@ -151,7 +169,7 @@ void luaE_freeCI (lua_State *L) { | |||
| 151 | void luaE_shrinkCI (lua_State *L) { | 169 | void luaE_shrinkCI (lua_State *L) { |
| 152 | CallInfo *ci = L->ci; | 170 | CallInfo *ci = L->ci; |
| 153 | CallInfo *next2; /* next's next */ | 171 | CallInfo *next2; /* next's next */ |
| 154 | L->nCcalls -= L->nci; /* to subtract removed elements from 'nCcalls' */ | 172 | L->nCcalls -= L->nci; /* subtract removed elements from 'nCcalls' */ |
| 155 | /* while there are two nexts */ | 173 | /* while there are two nexts */ |
| 156 | while (ci->next != NULL && (next2 = ci->next->next) != NULL) { | 174 | while (ci->next != NULL && (next2 = ci->next->next) != NULL) { |
| 157 | luaM_free(L, ci->next); /* free next */ | 175 | luaM_free(L, ci->next); /* free next */ |
| @@ -160,7 +178,7 @@ void luaE_shrinkCI (lua_State *L) { | |||
| 160 | next2->previous = ci; | 178 | next2->previous = ci; |
| 161 | ci = next2; /* keep next's next */ | 179 | ci = next2; /* keep next's next */ |
| 162 | } | 180 | } |
| 163 | L->nCcalls += L->nci; /* to subtract removed elements from 'nCcalls' */ | 181 | L->nCcalls += L->nci; /* adjust result */ |
| 164 | } | 182 | } |
| 165 | 183 | ||
| 166 | 184 | ||
| @@ -250,7 +268,6 @@ static void preinit_thread (lua_State *L, global_State *g) { | |||
| 250 | L->allowhook = 1; | 268 | L->allowhook = 1; |
| 251 | resethookcount(L); | 269 | resethookcount(L); |
| 252 | L->openupval = NULL; | 270 | L->openupval = NULL; |
| 253 | L->nny = 1; | ||
| 254 | L->status = LUA_OK; | 271 | L->status = LUA_OK; |
| 255 | L->errfunc = 0; | 272 | L->errfunc = 0; |
| 256 | } | 273 | } |
