Joakker / lua-json5

A json5 parser for luajit
MIT License
27 stars 6 forks source link

Neovim sometimes crashes on lua_getallocf called from json5.so #5

Open jedrzejboczar opened 5 days ago

jedrzejboczar commented 5 days ago

Hi, I am using lua-json5 for nvim-dap to load launch.json. I noticed that once in a while when I load dap configurations for the first time the whole Neovim crashes. From core dump using coredumpctl I can see the following:

Stack trace of thread 244848:
#0  0x000070e5d6e4c14d lua_getallocf (libluajit-5.1.so.2 + 0x1b14d)
#1  0x000070e5be22aaf8 n/a (/home/jb/.local/share/nvim/lazy/lua-json5/lua/json5.so + 0x1caf8)
ELF object binary architecture: AMD x86-64

and in GDB using bt:

(gdb) bt
#0  0x000070e5d6e4c14d in lua_getallocf (L=0x70e5cb9d4dd8, ud=0x7fff7102d600) at /usr/src/debug/luajit/LuaJIT-97813fb924edf822455f91a5fbbdfdb349e5984f/src/lj_api.c:1309
#1  0x000070e5be22aaf8 in ?? () from /home/jb/.local/share/nvim/lazy/lua-json5/lua/json5.so
#2  0x000070e5be236103 in ?? () from /home/jb/.local/share/nvim/lazy/lua-json5/lua/json5.so
#3  0x000070e5be232a7c in ?? () from /home/jb/.local/share/nvim/lazy/lua-json5/lua/json5.so
#4  0x000070e5be22a64c in ?? () from /home/jb/.local/share/nvim/lazy/lua-json5/lua/json5.so
#5  0x000070e5be2393d8 in ?? () from /home/jb/.local/share/nvim/lazy/lua-json5/lua/json5.so
#6  0x000070e5d6e37f06 in lj_BC_FUNCC () at buildvm_x86.dasc:857
#7  0x000070e5d6e4c0aa in lua_pcall (L=L@entry=0x70e5d6f5e380, nargs=nargs@entry=0, nresults=nresults@entry=1, errfunc=errfunc@entry=-2) at /usr/src/debug/luajit/LuaJIT-97813fb924edf822455f91a5fbbdfdb349e5984f/src/lj_api.c:1122
#8  0x0000594e115bff4e in nlua_pcall (nresults=1, lstate=0x70e5d6f5e380, nargs=0) at /usr/src/debug/neovim-git/neovim/src/nvim/lua/executor.c:174
#9  nlua_call_ref.constprop.0 (ref=<optimized out>, name=name@entry=0x0, args=..., err=err@entry=0x7fff7102e0e0, arena=<optimized out>, mode=<optimized out>) at /usr/src/debug/neovim-git/neovim/src/nvim/lua/executor.c:1608
#10 0x0000594e1130951f in map_execute_lua (may_repeat=true) at /usr/src/debug/neovim-git/neovim/src/nvim/getchar.c:3183
#11 0x0000594e113dfcbb in nv_colon (cap=0x7fff7102e2e0) at /usr/src/debug/neovim-git/neovim/src/nvim/normal.c:3174
#12 0x0000594e113dc3e6 in normal_execute (state=0x7fff7102e270, key=<optimized out>) at /usr/src/debug/neovim-git/neovim/src/nvim/normal.c:1235
#13 0x0000594e114d691b in state_enter (s=0x7fff7102e270) at /usr/src/debug/neovim-git/neovim/src/nvim/state.c:102
#14 0x0000594e113d900a in normal_enter (cmdwin=<optimized out>, noexmode=<optimized out>) at /usr/src/debug/neovim-git/neovim/src/nvim/normal.c:521
#15 0x0000594e11169187 in main (argc=<optimized out>, argv=<optimized out>) at /usr/src/debug/neovim-git/neovim/src/nvim/main.c:660

I don't have debug symbols for lua-json5 so that doesn't tell much, but GDB with debuginfod could point to the following:

#0  0x000070e5d6e4c14d in lua_getallocf (L=0x70e5cb9d4dd8, ud=0x7fff7102d600) at /usr/src/debug/luajit/LuaJIT-97813fb924edf822455f91a5fbbdfdb349e5984f/src/lj_api.c:1309
1309      if (ud) *ud = g->allocd;

so the question is what part of lua-json5 calls lua_getallocf with invalid arguments.

I will try to compile lua-json5 with debug symbols so that the next time it happens I can say more.

jedrzejboczar commented 17 hours ago

Here's stack trace with debug info:

(gdb) bt f
#0  0x000071b9f6d3014d in lua_getallocf (L=0x71b9f53c11e0, ud=0x7ffe1d62a320) at /usr/src/debug/luajit/LuaJIT-97813fb924edf822455f91a5fbbdfdb349e5984f/src/lj_api.c:1309
        g = 0x3ff0000000000000
#1  0x000071b9f0b989a9 in mlua::lua::Lua::create_table_from () from /home/jb/.local/share/nvim/lazy/lua-json5/lua/json5.so
No symbol table info available.
#2  0x000071b9f0b9dc16 in <lua_json5::val::Value as mlua::value::IntoLua>::into_lua () from /home/jb/.local/share/nvim/lazy/lua-json5/lua/json5.so
No symbol table info available.
#3  0x000071b9f0ba14fc in lua_json5::parser::parse () from /home/jb/.local/share/nvim/lazy/lua-json5/lua/json5.so
No symbol table info available.
#4  0x000071b9f0b98541 in mlua::lua::Lua::create_function::{{closure}} () from /home/jb/.local/share/nvim/lazy/lua-json5/lua/json5.so
No symbol table info available.
#5  0x000071b9f0ba946f in mlua::lua::Lua::create_callback::call_callback () from /home/jb/.local/share/nvim/lazy/lua-json5/lua/json5.so
No symbol table info available.
#6  0x000071b9f6d1bf06 in lj_BC_FUNCC () at buildvm_x86.dasc:857
No locals.
#7  0x000071b9f6d300aa in lua_pcall (L=L@entry=0x71b9f6e43380, nargs=nargs@entry=0, nresults=nresults@entry=1, errfunc=errfunc@entry=-2) at /usr/src/debug/luajit/LuaJIT-97813fb924edf822455f91a5fbbdfdb349e5984f/src/lj_api.c:1122
#8  0x00005e59ece5824e in nlua_pcall (nresults=1, lstate=0x71b9f6e43380, nargs=0) at /usr/src/debug/neovim-git/neovim/src/nvim/lua/executor.c:174
#9  nlua_call_ref.constprop.0 (ref=<optimized out>, name=name@entry=0x0, args=..., err=err@entry=0x7ffe1d62ad90, arena=<optimized out>, mode=<optimized out>) at /usr/src/debug/neovim-git/neovim/src/nvim/lua/executor.c:1608
#10 0x00005e59ecba159f in map_execute_lua (may_repeat=true) at /usr/src/debug/neovim-git/neovim/src/nvim/getchar.c:3183
#11 0x00005e59ecc77dbb in nv_colon (cap=0x7ffe1d62af90) at /usr/src/debug/neovim-git/neovim/src/nvim/normal.c:3174
#12 0x00005e59ecc744e6 in normal_execute (state=0x7ffe1d62af20, key=<optimized out>) at /usr/src/debug/neovim-git/neovim/src/nvim/normal.c:1235
#13 0x00005e59ecd6eadb in state_enter (s=0x7ffe1d62af20) at /usr/src/debug/neovim-git/neovim/src/nvim/state.c:102
#14 0x00005e59ecc7110a in normal_enter (cmdwin=<optimized out>, noexmode=<optimized out>) at /usr/src/debug/neovim-git/neovim/src/nvim/normal.c:521
#15 0x00005e59eca01187 in main (argc=<optimized out>, argv=<optimized out>) at /usr/src/debug/neovim-git/neovim/src/nvim/main.c:660

though it probably doesn't tell much... And si_addr = 0 so as far as I can understand this should be a null pointer dereference (https://sourceware.org/gdb/current/onlinedocs/gdb.html/Signals.html):

(gdb) p $_siginfo._sifields._sigfault
$4 = {
  si_addr = 0x0,
  _addr_lsb = 0,
  _addr_bnd = {
    _lower = 0x0,
    _upper = 0x0
  }
}

And for completeness:

(gdb) list
1304    }
1305
1306    LUA_API lua_Alloc lua_getallocf(lua_State *L, void **ud)
1307    {
1308      global_State *g = G(L);
1309      if (ud) *ud = g->allocd;
1310      return g->allocf;
1311    }
1312
1313    LUA_API void lua_setallocf(lua_State *L, lua_Alloc f, void *ud)
(gdb) disassemble
Dump of assembler code for function lua_getallocf:
   0x000071b9f6d30140 <+0>:     endbr64
   0x000071b9f6d30144 <+4>:     mov    0x10(%rdi),%rax
   0x000071b9f6d30148 <+8>:     test   %rsi,%rsi
   0x000071b9f6d3014b <+11>:    je     0x71b9f6d30154 <lua_getallocf+20>
=> 0x000071b9f6d3014d <+13>:    mov    0x8(%rax),%rdx
   0x000071b9f6d30151 <+17>:    mov    %rdx,(%rsi)
   0x000071b9f6d30154 <+20>:    mov    (%rax),%rax
   0x000071b9f6d30157 <+23>:    ret
End of assembler dump.
(gdb) i reg
rax            0x3ff0000000000000  4607182418800017408
rbx            0x10                16
rcx            0x5e5a15531644      103740997834308
rdx            0x5e5a15531500      103740997833984
rsi            0x7ffe1d62a320      140729391424288
rdi            0x71b9f53c11e0      125043497243104
rbp            0x1                 0x1
rsp            0x7ffe1d62a298      0x7ffe1d62a298
r8             0x5e5a135c0010      103740964864016
r9             0x7                 7
r10            0x5e5a155603f0      103740998026224
r11            0xbbb33a5e2038b5df  -4921525791843895841
r12            0x5e5a15531650      103740997834320
r13            0xffff0004          4294901764
r14            0x5e5a15531640      103740997834304
r15            0x1                 1
rip            0x71b9f6d3014d      0x71b9f6d3014d <lua_getallocf+13>
eflags         0x10202             [ IF RF ]
cs             0x33                51
ss             0x2b                43
ds             0x0                 0
es             0x0                 0
fs             0x0                 0
gs             0x0                 0
fs_base        0x71b9f69ce080      125043520364672
gs_base        0x0                 0
(gdb) p g
$5 = (global_State *) 0x3ff0000000000000
(gdb) p *g
Cannot access memory at address 0x3ff0000000000000
(gdb) ptype global_State
type = struct global_State {
    lua_Alloc allocf;
    void *allocd;
    GCState gc;
    GCstr strempty;
    uint8_t stremptyz;
    uint8_t hookmask;
    uint8_t dispatchmode;
    uint8_t vmevmask;
    StrInternState str;
    volatile int32_t vmstate;
    GCRef mainthref;
    SBuf tmpbuf;
    TValue tmptv;
    TValue tmptv2;
    Node nilnode;
    TValue registrytv;
    GCupval uvhead;
    int32_t hookcount;
    int32_t hookcstart;
    lua_Hook hookf;
    lua_CFunction wrapf;
    lua_CFunction panic;
    BCIns bc_cfunc_int;
    BCIns bc_cfunc_ext;
    GCRef cur_L;
    MRef jit_base;
    MRef ctype_state;
    PRNGState prng;
    GCRef gcroot[39];
}
(gdb)

though I'm not sure what is the issue, mov 0x8(%rax),%rdx looks like g->allocd (as allocd's offset in global_State is 8), so the address (global_State *) 0x3ff0000000000000 is invalid? Like not assigned to that process? (I'm not experienced with x86 assembly).