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 | } |