From 57f8414de1968b6f9f212140f2da14cba3b6dacb Mon Sep 17 00:00:00 2001 From: Roberto Ierusalimschy Date: Wed, 27 May 2009 14:11:27 -0300 Subject: [PATCH] small bug in 'luaV_concat' (L->top was left incorrect in some cases) --- lapi.c | 5 ++--- lobject.c | 5 ++--- lvm.c | 43 ++++++++++++++++++++++--------------------- lvm.h | 4 ++-- 4 files changed, 28 insertions(+), 29 deletions(-) diff --git a/lapi.c b/lapi.c index 69307a3c..ec26006b 100644 --- a/lapi.c +++ b/lapi.c @@ -1,5 +1,5 @@ /* -** $Id: lapi.c,v 2.75 2009/04/17 14:28:06 roberto Exp roberto $ +** $Id: lapi.c,v 2.76 2009/04/17 22:00:01 roberto Exp $ ** Lua API ** See Copyright Notice in lua.h */ @@ -1017,8 +1017,7 @@ LUA_API void lua_concat (lua_State *L, int n) { api_checknelems(L, n); if (n >= 2) { luaC_checkGC(L); - luaV_concat(L, n, cast_int(L->top - L->base) - 1); - L->top -= (n-1); + luaV_concat(L, n); } else if (n == 0) { /* push empty string */ setsvalue2s(L, L->top, luaS_newlstr(L, "", 0)); diff --git a/lobject.c b/lobject.c index bcd62086..f02b2ce0 100644 --- a/lobject.c +++ b/lobject.c @@ -1,5 +1,5 @@ /* -** $Id: lobject.c,v 2.28 2008/01/30 18:05:23 roberto Exp roberto $ +** $Id: lobject.c,v 2.29 2009/02/19 17:18:25 roberto Exp $ ** Some generic functions over Lua objects ** See Copyright Notice in lua.h */ @@ -162,8 +162,7 @@ const char *luaO_pushvfstring (lua_State *L, const char *fmt, va_list argp) { fmt = e+2; } pushstr(L, fmt); - luaV_concat(L, n+1, cast_int(L->top - L->base) - 1); - L->top -= n; + luaV_concat(L, n+1); return svalue(L->top - 1); } diff --git a/lvm.c b/lvm.c index a6207984..9842bcb9 100644 --- a/lvm.c +++ b/lvm.c @@ -1,5 +1,5 @@ /* -** $Id: lvm.c,v 2.87 2009/04/30 17:42:21 roberto Exp roberto $ +** $Id: lvm.c,v 2.88 2009/05/22 15:19:54 roberto Exp $ ** Lua virtual machine ** See Copyright Notice in lua.h */ @@ -264,24 +264,22 @@ int luaV_equalval_ (lua_State *L, const TValue *t1, const TValue *t2) { } -void luaV_concat (lua_State *L, int total, int last) { +void luaV_concat (lua_State *L, int total) { + lua_assert(total >= 2); do { - StkId top = L->base + last + 1; + StkId top = L->top; int n = 2; /* number of elements handled in this pass (at least 2) */ if (!(ttisstring(top-2) || ttisnumber(top-2)) || !tostring(L, top-1)) { - L->top = top; /* set top to current position (in case of yield) */ if (!call_binTM(L, top-2, top-1, top-2, TM_CONCAT)) luaG_concaterror(L, top-2, top-1); - L->top = L->ci->top; /* restore top */ - } - else if (tsvalue(top-1)->len == 0) { /* second operand is empty? */ - (void)tostring(L, top - 2); /* result is first operand */ ; } + else if (tsvalue(top-1)->len == 0) /* second operand is empty? */ + (void)tostring(L, top - 2); /* result is first operand */ else if (ttisstring(top-2) && tsvalue(top-2)->len == 0) { - setsvalue2s(L, top-2, rawtsvalue(top-1)); /* result is second op. */ + setsvalue2s(L, top-2, rawtsvalue(top-1)); /* result is second op. */ } else { - /* at least two (non-empty) string values; get as many as possible */ + /* at least two non-empty string values; get as many as possible */ size_t tl = tsvalue(top-1)->len; char *buffer; int i; @@ -300,8 +298,8 @@ void luaV_concat (lua_State *L, int total, int last) { } setsvalue2s(L, top-n, luaS_newlstr(L, buffer, tl)); } - total -= n-1; /* got `n' strings to create 1 new */ - last -= n-1; + total -= n-1; /* got 'n' strings to create 1 new */ + L->top -= n-1; /* poped 'n' strings and pushed one */ } while (total > 1); /* repeat until only 1 result left */ } @@ -381,16 +379,17 @@ void luaV_finishOp (lua_State *L) { break; } case OP_CONCAT: { - StkId top = L->top - 1; /* top when __concat was called */ - int last = cast_int(top - ci->base) - 2; /* last element and ... */ - int b = GETARG_B(inst); /* ... first element to concatenate */ - int total = last - b + 1; /* number of elements to concatenate */ + StkId top = L->top - 1; /* top when 'call_binTM' was called */ + int b = GETARG_B(inst); /* first element to concatenate */ + int total = top - 1 - (ci->base + b); /* elements yet to concatenate */ setobj2s(L, top - 2, top); /* put TM result in proper position */ - L->top = ci->top; /* correct top */ - if (total > 1) /* are there elements to concat? */ - luaV_concat(L, total, last); /* concat them (may yield again) */ + if (total > 1) { /* are there elements to concat? */ + L->top = top - 1; /* top is one after last element (at top-2) */ + luaV_concat(L, total); /* concat them (may yield again) */ + } /* move final result to final position */ - setobj2s(L, ci->base + GETARG_A(inst), ci->base + b); + setobj2s(L, ci->base + GETARG_A(inst), L->top - 1); + L->top = ci->top; /* restore top */ break; } case OP_TFORCALL: { @@ -586,7 +585,9 @@ void luaV_execute (lua_State *L) { case OP_CONCAT: { int b = GETARG_B(i); int c = GETARG_C(i); - Protect(luaV_concat(L, c-b+1, c); luaC_checkGC(L)); + L->top = base + c + 1; /* mark the end of concat operands */ + Protect(luaV_concat(L, c-b+1); luaC_checkGC(L)); + L->top = ci->top; /* restore top */ setobjs2s(L, RA(i), base+b); continue; } diff --git a/lvm.h b/lvm.h index 2d68f406..0b45ca0d 100644 --- a/lvm.h +++ b/lvm.h @@ -1,5 +1,5 @@ /* -** $Id: lvm.h,v 2.7 2008/08/26 13:27:42 roberto Exp roberto $ +** $Id: lvm.h,v 2.8 2009/03/10 17:14:37 roberto Exp $ ** Lua virtual machine ** See Copyright Notice in lua.h */ @@ -34,6 +34,6 @@ LUAI_FUNC void luaV_settable (lua_State *L, const TValue *t, TValue *key, StkId val); LUAI_FUNC void luaV_finishOp (lua_State *L); LUAI_FUNC void luaV_execute (lua_State *L); -LUAI_FUNC void luaV_concat (lua_State *L, int total, int last); +LUAI_FUNC void luaV_concat (lua_State *L, int total); #endif