며칠 전에 프로그램이 중단되었습니다. 루아 코드에서 충돌을 발견했습니다. 그래서 루아 코드를 확인해 스택 오버 플로우를 발견했다.lua 스택 오버 플로우, 이것이 버그입니까?
기능 luaD_precall
에서이 코드를보고하십시오 :의 p->maxstacksize
라인 5 전에 79 내 프로그램에서
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;
, 현재 스택 크기 통화 luaD_checkstack
후, 51이며, 스택 크기는 130
lua 함수는 vararg를 사용하므로 14 행까지 실행됩니다. 함수 adjust_varargs
이 호출됩니다. 기능 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 */
는 루아 기능 사용 "인수는"그래서 luaC_checkGC
가 호출됩니다. luaC_checkGC
에서 현재 lua 스택 크기는 65로 줄어 듭니다! 이 같은 호출 스택 : 프로그램 실행 27 줄을 때
luaC_step() singlestep() propagatemark() traversestack() checkstacksizes() luaD_reallocstack()
그러나 p->maxstacksize
가 79이, 스택 크기가 ... 충분하지 않습니다는 L->top
는 다음 작업에, 충돌의 원인이됩니다, L->stack_last
보다 큰 !
사용자 C/루아 코드를 보면이 충돌을 트리거하기 위해 무엇을 좋아 하는가? – u0b34a0f6ae
그런 시나리오를 만들기 위해 작성한 코드를 게시하지 않으면 버그를 발견했는지 여부를 알 수 없습니다. L-가> 최고 L-보다 큰 경우 – Puppy
는> stack_last 내 스크립트에서, 다음 작업 후, 스택의 성장,이 작업> L-에서, 새로운 스택 기존의 스택을 복사합니다 스택에 폐쇄를 새 스택을 L-> stack_last로 설정하면 클로저가 복사되지 않습니다. 이제 클로저가 초기화되지 않았습니다. 폐쇄가 호출되면 불법적 인 메모리 액세스가 발생하고 프로그램이 중단됩니다! – xiayong