Переполнение стека lua, это ошибка? - PullRequest
0 голосов
/ 07 мая 2010

Несколько дней назад произошел сбой нашей программы. Я нашел сбой в коде Луа. Поэтому я проверяю код lua, обнаружил переполнение стека.

Пожалуйста, посмотрите этот код в функции luaD_precall:

1  if (!cl->isC) {  /* Lua function? prepare its call */
2       CallInfo *ci;
3       StkId st, base;
4       Proto *p = cl->p;
5       luaD_checkstack(L, p->maxstacksize);
6       func = restorestack(L, funcr);
7       if (!p->is_vararg) {  /* no varargs? */
8              base = func + 1;
9              if (L->top > base + p->numparams)
10             L->top = base + p->numparams;
11      }
12      else {  /* vararg function */
13             int nargs = cast_int(L->top - func) - 1;
14             base = adjust_varargs(L, p, nargs);
15             func = restorestack(L, funcr);  /* previous call may change the stack */
16      }
17      ci = inc_ci(L);  /* now `enter' new function */
18      ci->func = func;
19      L->base = ci->base = base;
20      ci->top = L->base + p->maxstacksize;
21      lua_assert(ci->top <= L->stack_last);
22      L->savedpc = p->code;  /* starting point */
23      ci->tailcalls = 0;
24      ci->nresults = nresults;
25      for (st = L->top; st < ci->top; st++)
26             setnilvalue(st);
27      L->top = ci->top;

В моей программе p->maxstacksize равно 79 перед строкой 5, текущий размер стека равен 51, после вызова luaD_checkstack размер стека увеличивается до 130.

Функция lua использует vararg, поэтому будет работать со строкой 14. Будет вызвана функция adjust_varargs.

static StkId adjust_varargs (lua_State *L, Proto *p, int actual) {
        int i;
        int nfixargs = p->numparams;
       Table *htab = NULL;
       StkId base, fixed;
       for (; actual < nfixargs; ++actual)
           setnilvalue(L->top++);
#if defined(LUA_COMPAT_VARARG)
       if (p->is_vararg & VARARG_NEEDSARG) { /* compat. with old-style vararg? */
           int nvar = actual - nfixargs;  /* number of extra arguments */
           lua_assert(p->is_vararg & VARARG_HASARG);
           luaC_checkGC(L);
       htab = luaH_new(L, nvar, 1);  /* create `arg' table */

В функции adjust_varargs() функция lua использует «arg», поэтому будет вызываться luaC_checkGC. В luaC_checkGC текущий размер стека lua будет уменьшен до 65! Стек вызовов выглядит так:

luaC_step()
singlestep()
propagatemark()
traversestack()
checkstacksizes()
luaD_reallocstack()

Но p->maxstacksize равно 79, стеков недостаточно ... Когда программа запускается в строке 27, L->top больше L->stack_last, в следующей операции произойдет сбой!

1 Ответ

0 голосов
/ 08 мая 2010

Это ошибка?

Мне кажется, что это ошибка, но я не специалист по внутренним компонентам Lua на этом уровне.Похоже, у вас есть довольно последовательное объяснение, поэтому, если вы также можете создать простое приложение, которое делает ошибку воспроизводимой, вам следует отправить все это в виде отчета об ошибке на lua@bazar2.conectiva.com.br.

...