lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]

It looks like you may have popped the coroutine prematurely — you may have retained a C pointer to it, but that won’t prevent Lua from garbage collecting it (which will probably happen non-deterministically, hence the difficulty in reproducing).

You need to leave the coroutine on L’s stack so that it doesn’t go away.  In order to get it out of the way so that you can call lua_xmove, try applying a lua_rotate to L’s stack to move the coroutine below the function and parameters.


On Sat, Aug 14, 2021 at 8:17 PM Paul K <> wrote:
Hi all,

I'm working on a project that embeds Lua 5.4.3 and calls
luaL_traceback to generate a stack trace. During one of the runs I got
an ASAN error with the following stack trace:

asan error: heap use after free 8-byte load at 0x100080939860 shadow
7770000ff490 0000006aed63 __die+0x34
7770000ff4a0 000000720f9b __asan_die+0x2b
7770000ff4b0 000000721337 __asan_report_memory_fault+0x1d7
7770000ff5e0 000000721d03 __asan_report_load+0x13
7770000ff5f0 00000071fe01 __asan_report_load8+0x22
7770000ff600 0000005a2029 lua_getinfo+0x287
7770000ff640 00000059bc0c pushglobalfuncname+0x2e
7770000ff670 00000059bce7 pushfuncname+0x17
7770000ff690 00000059eca6 luaL_traceback+0x31f
7770000ffca0 00000042913c LuaCallWithTrace+0xf4

I have *not* been able to reproduce this more than once, but it did
happen and I'm interested if anyone can suggest what may be going on
and if the issue is with luaL_traceback or somewhere outside of it.
The stack was only 2 levels deep when that error was thrown and I
tried to reproduce it with exactly the same message and stack content
to no avail.

Just in case, the code that is calling luaL_traceback is shown below
(I'm using lua_resume instead of a pcall to capture the stack trace).
Thank you.


static int LuaPCallWithTrace(lua_State *L, int nargs, int nres) {
  int nresults, status;
  // create a coroutine to retrieve traceback on failure
  lua_State *co = lua_newthread(L);
  // pop the coroutine, so that the function is at the top
  lua_pop(L, 1);
  // move the function (and arguments) to the top of the coro stack
  lua_xmove(L, co, nargs+1);
  // resume the coroutine thus executing the function
  status = lua_resume(co, L, nargs, &nresults);
  if (status != LUA_OK && status != LUA_YIELD) {
    // move the error message
    lua_xmove(co, L, 1);
    // replace the error with the traceback on failure
    luaL_traceback(L, co, lua_tostring(L, -1), 0);
    lua_remove(L, -2); // remove the error message
  } else {
    // move results to the main stack
    lua_xmove(co, L, nresults);
    // make sure the stack has enough space to grow
    luaL_checkstack(L, nres - nresults, NULL);
    // grow the stack in case returned fewer results
    // than the caller expects, as lua_resume
    // doesn't adjust the stack for expected results
    for (; nresults < nres; nresults++) lua_pushnil(L);
  return status;