diff options
Diffstat (limited to 'apps/plugins/lua/lvm.c')
-rw-r--r-- | apps/plugins/lua/lvm.c | 42 |
1 files changed, 35 insertions, 7 deletions
diff --git a/apps/plugins/lua/lvm.c b/apps/plugins/lua/lvm.c index 35a931d7a1..4979b6a88e 100644 --- a/apps/plugins/lua/lvm.c +++ b/apps/plugins/lua/lvm.c | |||
@@ -49,9 +49,10 @@ int luaV_tostring (lua_State *L, StkId obj) { | |||
49 | return 0; | 49 | return 0; |
50 | else { | 50 | else { |
51 | char s[LUAI_MAXNUMBER2STR]; | 51 | char s[LUAI_MAXNUMBER2STR]; |
52 | ptrdiff_t objr = savestack(L, obj); | ||
52 | lua_Number n = nvalue(obj); | 53 | lua_Number n = nvalue(obj); |
53 | lua_number2str(s, n); | 54 | lua_number2str(s, n); |
54 | setsvalue2s(L, obj, luaS_new(L, s)); | 55 | setsvalue2s(L, restorestack(L, objr), luaS_new(L, s)); |
55 | return 1; | 56 | return 1; |
56 | } | 57 | } |
57 | } | 58 | } |
@@ -134,6 +135,9 @@ void luaV_gettable (lua_State *L, const TValue *t, TValue *key, StkId val) { | |||
134 | void luaV_settable (lua_State *L, const TValue *t, TValue *key, StkId val) { | 135 | void luaV_settable (lua_State *L, const TValue *t, TValue *key, StkId val) { |
135 | int loop; | 136 | int loop; |
136 | TValue temp; | 137 | TValue temp; |
138 | setnilvalue(L->top); | ||
139 | L->top++; | ||
140 | fixedstack(L); | ||
137 | for (loop = 0; loop < MAXTAGLOOP; loop++) { | 141 | for (loop = 0; loop < MAXTAGLOOP; loop++) { |
138 | const TValue *tm; | 142 | const TValue *tm; |
139 | if (ttistable(t)) { /* `t' is a table? */ | 143 | if (ttistable(t)) { /* `t' is a table? */ |
@@ -141,6 +145,8 @@ void luaV_settable (lua_State *L, const TValue *t, TValue *key, StkId val) { | |||
141 | TValue *oldval = luaH_set(L, h, key); /* do a primitive set */ | 145 | TValue *oldval = luaH_set(L, h, key); /* do a primitive set */ |
142 | if (!ttisnil(oldval) || /* result is no nil? */ | 146 | if (!ttisnil(oldval) || /* result is no nil? */ |
143 | (tm = fasttm(L, h->metatable, TM_NEWINDEX)) == NULL) { /* or no TM? */ | 147 | (tm = fasttm(L, h->metatable, TM_NEWINDEX)) == NULL) { /* or no TM? */ |
148 | L->top--; | ||
149 | unfixedstack(L); | ||
144 | setobj2t(L, oldval, val); | 150 | setobj2t(L, oldval, val); |
145 | h->flags = 0; | 151 | h->flags = 0; |
146 | luaC_barriert(L, h, val); | 152 | luaC_barriert(L, h, val); |
@@ -151,12 +157,15 @@ void luaV_settable (lua_State *L, const TValue *t, TValue *key, StkId val) { | |||
151 | else if (ttisnil(tm = luaT_gettmbyobj(L, t, TM_NEWINDEX))) | 157 | else if (ttisnil(tm = luaT_gettmbyobj(L, t, TM_NEWINDEX))) |
152 | luaG_typeerror(L, t, "index"); | 158 | luaG_typeerror(L, t, "index"); |
153 | if (ttisfunction(tm)) { | 159 | if (ttisfunction(tm)) { |
160 | L->top--; | ||
161 | unfixedstack(L); | ||
154 | callTM(L, tm, t, key, val); | 162 | callTM(L, tm, t, key, val); |
155 | return; | 163 | return; |
156 | } | 164 | } |
157 | /* else repeat with `tm' */ | 165 | /* else repeat with `tm' */ |
158 | setobj(L, &temp, tm); /* avoid pointing inside table (may rehash) */ | 166 | setobj(L, &temp, tm); /* avoid pointing inside table (may rehash) */ |
159 | t = &temp; | 167 | t = &temp; |
168 | setobj2s(L, L->top-1, t); /* need to protect value from EGC. */ | ||
160 | } | 169 | } |
161 | luaG_runerror(L, "loop in settable"); | 170 | luaG_runerror(L, "loop in settable"); |
162 | } | 171 | } |
@@ -284,8 +293,11 @@ void luaV_concat (lua_State *L, int total, int last) { | |||
284 | StkId top = L->base + last + 1; | 293 | StkId top = L->base + last + 1; |
285 | int n = 2; /* number of elements handled in this pass (at least 2) */ | 294 | int n = 2; /* number of elements handled in this pass (at least 2) */ |
286 | if (!(ttisstring(top-2) || ttisnumber(top-2)) || !tostring(L, top-1)) { | 295 | if (!(ttisstring(top-2) || ttisnumber(top-2)) || !tostring(L, top-1)) { |
287 | if (!call_binTM(L, top-2, top-1, top-2, TM_CONCAT)) | 296 | if (!call_binTM(L, top-2, top-1, top-2, TM_CONCAT)) { |
297 | /* restore 'top' pointer, since stack might have been reallocted */ | ||
298 | top = L->base + last + 1; | ||
288 | luaG_concaterror(L, top-2, top-1); | 299 | luaG_concaterror(L, top-2, top-1); |
300 | } | ||
289 | } else if (tsvalue(top-1)->len == 0) /* second op is empty? */ | 301 | } else if (tsvalue(top-1)->len == 0) /* second op is empty? */ |
290 | (void)tostring(L, top - 2); /* result is first op (as string) */ | 302 | (void)tostring(L, top - 2); /* result is first op (as string) */ |
291 | else { | 303 | else { |
@@ -293,12 +305,14 @@ void luaV_concat (lua_State *L, int total, int last) { | |||
293 | size_t tl = tsvalue(top-1)->len; | 305 | size_t tl = tsvalue(top-1)->len; |
294 | char *buffer; | 306 | char *buffer; |
295 | int i; | 307 | int i; |
308 | fixedstack(L); | ||
296 | /* collect total length */ | 309 | /* collect total length */ |
297 | for (n = 1; n < total && tostring(L, top-n-1); n++) { | 310 | for (n = 1; n < total && tostring(L, top-n-1); n++) { |
298 | size_t l = tsvalue(top-n-1)->len; | 311 | size_t l = tsvalue(top-n-1)->len; |
299 | if (l >= MAX_SIZET - tl) luaG_runerror(L, "string length overflow"); | 312 | if (l >= MAX_SIZET - tl) luaG_runerror(L, "string length overflow"); |
300 | tl += l; | 313 | tl += l; |
301 | } | 314 | } |
315 | G(L)->buff.n = tl; | ||
302 | buffer = luaZ_openspace(L, &G(L)->buff, tl); | 316 | buffer = luaZ_openspace(L, &G(L)->buff, tl); |
303 | tl = 0; | 317 | tl = 0; |
304 | for (i=n; i>0; i--) { /* concat all strings */ | 318 | for (i=n; i>0; i--) { /* concat all strings */ |
@@ -307,6 +321,8 @@ void luaV_concat (lua_State *L, int total, int last) { | |||
307 | tl += l; | 321 | tl += l; |
308 | } | 322 | } |
309 | setsvalue2s(L, top-n, luaS_newlstr(L, buffer, tl)); | 323 | setsvalue2s(L, top-n, luaS_newlstr(L, buffer, tl)); |
324 | luaZ_resetbuffer(&G(L)->buff); | ||
325 | unfixedstack(L); | ||
310 | } | 326 | } |
311 | total -= n-1; /* got `n' strings to create 1 new */ | 327 | total -= n-1; /* got `n' strings to create 1 new */ |
312 | last -= n-1; | 328 | last -= n-1; |
@@ -332,8 +348,13 @@ static void Arith (lua_State *L, StkId ra, const TValue *rb, | |||
332 | default: lua_assert(0); break; | 348 | default: lua_assert(0); break; |
333 | } | 349 | } |
334 | } | 350 | } |
335 | else if (!call_binTM(L, rb, rc, ra, op)) | 351 | else { |
336 | luaG_aritherror(L, rb, rc); | 352 | ptrdiff_t br = savestack(L, rb); |
353 | ptrdiff_t cr = savestack(L, rc); | ||
354 | if (!call_binTM(L, rb, rc, ra, op)) { | ||
355 | luaG_aritherror(L, restorestack(L, br), restorestack(L, cr)); | ||
356 | } | ||
357 | } | ||
337 | } | 358 | } |
338 | 359 | ||
339 | 360 | ||
@@ -461,7 +482,9 @@ void luaV_execute (lua_State *L, int nexeccalls) { | |||
461 | case OP_NEWTABLE: { | 482 | case OP_NEWTABLE: { |
462 | int b = GETARG_B(i); | 483 | int b = GETARG_B(i); |
463 | int c = GETARG_C(i); | 484 | int c = GETARG_C(i); |
464 | sethvalue(L, ra, luaH_new(L, luaO_fb2int(b), luaO_fb2int(c))); | 485 | Table *h; |
486 | Protect(h = luaH_new(L, luaO_fb2int(b), luaO_fb2int(c))); | ||
487 | sethvalue(L, RA(i), h); | ||
465 | Protect(luaC_checkGC(L)); | 488 | Protect(luaC_checkGC(L)); |
466 | continue; | 489 | continue; |
467 | } | 490 | } |
@@ -547,9 +570,10 @@ void luaV_execute (lua_State *L, int nexeccalls) { | |||
547 | break; | 570 | break; |
548 | } | 571 | } |
549 | default: { /* try metamethod */ | 572 | default: { /* try metamethod */ |
573 | ptrdiff_t br = savestack(L, rb); | ||
550 | Protect( | 574 | Protect( |
551 | if (!call_binTM(L, rb, luaO_nilobject, ra, TM_LEN)) | 575 | if (!call_binTM(L, rb, luaO_nilobject, ra, TM_LEN)) |
552 | luaG_typeerror(L, rb, "get length of"); | 576 | luaG_typeerror(L, restorestack(L, br), "get length of"); |
553 | ) | 577 | ) |
554 | } | 578 | } |
555 | } | 579 | } |
@@ -723,6 +747,7 @@ void luaV_execute (lua_State *L, int nexeccalls) { | |||
723 | int c = GETARG_C(i); | 747 | int c = GETARG_C(i); |
724 | int last; | 748 | int last; |
725 | Table *h; | 749 | Table *h; |
750 | fixedstack(L); | ||
726 | if (n == 0) { | 751 | if (n == 0) { |
727 | n = cast_int(L->top - ra) - 1; | 752 | n = cast_int(L->top - ra) - 1; |
728 | L->top = L->ci->top; | 753 | L->top = L->ci->top; |
@@ -738,6 +763,7 @@ void luaV_execute (lua_State *L, int nexeccalls) { | |||
738 | setobj2t(L, luaH_setnum(L, h, last--), val); | 763 | setobj2t(L, luaH_setnum(L, h, last--), val); |
739 | luaC_barriert(L, h, val); | 764 | luaC_barriert(L, h, val); |
740 | } | 765 | } |
766 | unfixedstack(L); | ||
741 | continue; | 767 | continue; |
742 | } | 768 | } |
743 | case OP_CLOSE: { | 769 | case OP_CLOSE: { |
@@ -750,7 +776,9 @@ void luaV_execute (lua_State *L, int nexeccalls) { | |||
750 | int nup, j; | 776 | int nup, j; |
751 | p = cl->p->p[GETARG_Bx(i)]; | 777 | p = cl->p->p[GETARG_Bx(i)]; |
752 | nup = p->nups; | 778 | nup = p->nups; |
779 | fixedstack(L); | ||
753 | ncl = luaF_newLclosure(L, nup, cl->env); | 780 | ncl = luaF_newLclosure(L, nup, cl->env); |
781 | setclvalue(L, ra, ncl); | ||
754 | ncl->l.p = p; | 782 | ncl->l.p = p; |
755 | for (j=0; j<nup; j++, pc++) { | 783 | for (j=0; j<nup; j++, pc++) { |
756 | if (GET_OPCODE(*pc) == OP_GETUPVAL) | 784 | if (GET_OPCODE(*pc) == OP_GETUPVAL) |
@@ -760,7 +788,7 @@ void luaV_execute (lua_State *L, int nexeccalls) { | |||
760 | ncl->l.upvals[j] = luaF_findupval(L, base + GETARG_B(*pc)); | 788 | ncl->l.upvals[j] = luaF_findupval(L, base + GETARG_B(*pc)); |
761 | } | 789 | } |
762 | } | 790 | } |
763 | setclvalue(L, ra, ncl); | 791 | unfixedstack(L); |
764 | Protect(luaC_checkGC(L)); | 792 | Protect(luaC_checkGC(L)); |
765 | continue; | 793 | continue; |
766 | } | 794 | } |