Lua栈溢出,这是一个bug吗?

几天前,我们的程序崩溃了。我在lua代码中发现了崩溃的原因。于是我检查了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在第5行之前为79,当前堆栈大小为51,在调用luaD_checkstack之后,堆栈大小增长到了130。

这个lua函数使用了可变参数,因此将运行到第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,在下一次操作中会导致崩溃!

原文链接 https://stackoverflow.com/questions/2788963

点赞
stackoverflow用户41661
stackoverflow用户41661

这是个 bug 吗?

对我来说,看起来是个 bug,但我不是 Lua 的内部专家。虽然你已经给出了一个相当连贯的解释,但如果你也可以构建一个简单的应用程序来重现这个 bug,你应该将整个过程作为错误报告发送给 lua@bazar2.conectiva.com.br

2010-05-08 01:17:09