[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: Corrupted pointer in luaD_precall after stack grow/reallocation
- From: ijsf <ijsf@...>
- Date: Sat, 15 Oct 2011 16:41:14 +0200
I have recently noticed a serious problem in Lua 5.1.4's luaD_precall
function using Valgrind.
The bug is basically a corrupt (outdated) stack pointer to a function,
after the stack has been grown before calling a C function, though it
may affect other types of calls as well.
In this specific case, my Lua script was calling an arbitrary C
function. Here's the valgrind log and call stack:
==28698== Invalid read of size 4
==28698== at 0x9ABD: luaD_precall (ldo.c:455)
==28698== by 0x9D8B: luaD_call (ldo.c:518)
==28698== by 0x1736A: callTMres (lvm.c:110)
==28698== by 0x1773C: luaV_gettable (lvm.c:148)
==28698== by 0x18D5E: luaV_execute (lvm.c:486)
==28698== by 0x9E78: f_coresume (ldo.c:532)
==28698== by 0x8A8C: luaD_rawrunprotected (ldo.c:141)
==28698== by 0xA081: lua_resume (ldo.c:588)
==28698== by 0x319BC: CVM::Update() (CVM.cpp:1358)
==28698== by 0x370F9: CHypervisorWorker::Update() (CHypervisor.cpp:185)
==28698== by 0x3734E: CHypervisorWorker::ThreadFunc(void*)
(CHypervisor.cpp:130)
==28698== by 0x2BC054: _pthread_start (in /usr/lib/libSystem.B.dylib)
==28698== Address 0x55cf24 is 356 bytes inside a block of size 540 free'd
==28698== at 0xD8A87: realloc (vg_replace_malloc.c:525)
==28698== by 0x1D415: l_alloc (lauxlib.c:715)
==28698== by 0xF1C9: luaM_realloc_ (lmem.c:79)
==28698== by 0x8F5B: luaD_reallocstack (ldo.c:256)
==28698== by 0x90C1: luaD_growstack (ldo.c:275)
==28698== by 0x99D2: luaD_precall (ldo.c:442)
==28698== by 0x9D8B: luaD_call (ldo.c:518)
==28698== by 0x1736A: callTMres (lvm.c:110)
==28698== by 0x1773C: luaV_gettable (lvm.c:148)
==28698== by 0x18D5E: luaV_execute (lvm.c:486)
==28698== by 0x9E78: f_coresume (ldo.c:532)
==28698== by 0x8A8C: luaD_rawrunprotected (ldo.c:141)
After some debugging, I found out that 0x55CF40 was the old L->top
pointer before growing/reallocation (and was updated to 0x582280).
Basically, what's happening is the following (luaD_precall):
...
else { /* if is a C function, call it */
CallInfo *ci;
int n;
luaD_checkstack(L, LUA_MINSTACK); /* ensure minimum stack size */
During the call, apparently the stack is too small, so luaD_checkstack
calls luaD_growstack (as you can see in the valgrind log). That's all
fine, and luaD_precall continues:
...
if (ttisfunction(func))
Well, luaD_growstack rellocates the stack, and updates (among others)
L->top.. however, the variable 'func' was passed into luaD_precall by
luaD_call and subsequently passed in by callTMres:
...
luaD_call(L, L->top - 3, 1, 0);
That second argument will form the variable 'func' in luaD_call and
luaD_precall. You can see that 'func' will point at the stack as it
was in callTMres BEFORE the stack was reallocated. As the stack is
reallocated later on in luaD_precall, 'func' is never updated and
leads to a corrupted pointer.
I appreciate any input on this potential bug. Will be looking for a
fix/patch today.