summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--apps/plugins/lua/lvm.c11
1 files changed, 7 insertions, 4 deletions
diff --git a/apps/plugins/lua/lvm.c b/apps/plugins/lua/lvm.c
index 4979b6a88e..52d12d0371 100644
--- a/apps/plugins/lua/lvm.c
+++ b/apps/plugins/lua/lvm.c
@@ -290,22 +290,25 @@ int luaV_equalval (lua_State *L, const TValue *t1, const TValue *t2) {
void luaV_concat (lua_State *L, int total, int last) {
do {
+ /* Any call which does a memory allocation may trim the stack,
+ invalidating top unless the stack is fixed during the allocation */
StkId top = L->base + last + 1;
+ fixedstack(L);
int n = 2; /* number of elements handled in this pass (at least 2) */
if (!(ttisstring(top-2) || ttisnumber(top-2)) || !tostring(L, top-1)) {
+ unfixedstack(L);
if (!call_binTM(L, top-2, top-1, top-2, TM_CONCAT)) {
/* restore 'top' pointer, since stack might have been reallocted */
top = L->base + last + 1;
luaG_concaterror(L, top-2, top-1);
}
- } else if (tsvalue(top-1)->len == 0) /* second op is empty? */
+ } else if (tsvalue(top-1)->len == 0) { /* second op is empty? */
(void)tostring(L, top - 2); /* result is first op (as string) */
- else {
+ } else {
/* at least two string values; get as many as possible */
size_t tl = tsvalue(top-1)->len;
char *buffer;
int i;
- fixedstack(L);
/* collect total length */
for (n = 1; n < total && tostring(L, top-n-1); n++) {
size_t l = tsvalue(top-n-1)->len;
@@ -322,10 +325,10 @@ void luaV_concat (lua_State *L, int total, int last) {
}
setsvalue2s(L, top-n, luaS_newlstr(L, buffer, tl));
luaZ_resetbuffer(&G(L)->buff);
- unfixedstack(L);
}
total -= n-1; /* got `n' strings to create 1 new */
last -= n-1;
+ unfixedstack(L);
} while (total > 1); /* repeat until only 1 result left */
}