[MacPorts] #68126: neovim @0.9.1_1: segmentation fault

MacPorts noreply at macports.org
Sat Dec 16 23:18:53 UTC 2023


#68126: neovim @0.9.1_1: segmentation fault
--------------------------------+----------------------------
  Reporter:  dlamija            |      Owner:  raimue
      Type:  defect             |     Status:  assigned
  Priority:  Normal             |  Milestone:
 Component:  ports              |    Version:  2.8.1
Resolution:                     |   Keywords:  ventura sonoma
      Port:  neovim luv-luajit  |
--------------------------------+----------------------------

Comment (by echesakov):

 I think the issue is due to two conflicting definitions of macro
 `LUA_REGISTRYINDEX` used by `luv-luajit` and `luajit` ports.

 The macro definition seems to change between 5.1 and 5.3 versions of Lua
 language:

 {{{
 find /opt/local/include -name 'lua\.h' | xargs grep 'define
 LUA_REGISTRYINDEX'
 /opt/local/include/lua5.1/lua.h:#define LUA_REGISTRYINDEX       (-10000)
 /opt/local/include/luajit-2.1/lua.h:#define LUA_REGISTRYINDEX   (-10000)
 /opt/local/include/lua5.3/lua.h:#define LUA_REGISTRYINDEX
 (-LUAI_MAXSTACK - 1000)
 /opt/local/include/lua.h:#define LUA_REGISTRYINDEX      (-LUAI_MAXSTACK -
 1000)
 }}}

 When port `luv-luajit` and, file `luv.c` in particular, is compiled it
 picks up the definition from `/opt/local/include/lua.h` (provided by port
 `lua`).

 Note `-I/opt/local/include` used in the following command line:

 {{{
 [ 50%] Building C object CMakeFiles/libluv.dir/src/luv.c.o
 /usr/bin/clang -Dlibluv_EXPORTS -I/opt/local/include
 -I/opt/local/include/luajit-2.1
 -I/opt/local/var/macports/build/_opt_local_var_macports_sources_rsync.macports.org_macports_release_tarballs_ports_devel_luv
 /luv-luajit/work/luv-1.45.0-0/deps/lua-compat-5.3/c-api -pipe -Os -DNDEBUG
 -I/opt/local/include
 -isysroot/Library/Developer/CommandLineTools/SDKs/MacOSX14.sdk -arch arm64
 -isysroot /Library/Developer/CommandLineTools/SDKs/MacOSX14.sdk -mmacosx-
 version-min=14.0 -fPIC -MD -MT CMakeFiles/libluv.dir/src/luv.c.o -MF
 CMakeFiles/libluv.dir/src/luv.c.o.d -o CMakeFiles/libluv.dir/src/luv.c.o
 -c
 /opt/local/var/macports/build/_opt_local_var_macports_sources_rsync.macports.org_macports_release_tarballs_ports_devel_luv
 /luv-luajit/work/luv-1.45.0-0/src/luv.c
 }}}

 By running preprocessor on `luv.c` and peeking at the definition of
 `luv_context` function:

 {{{
 cd
 "/opt/local/var/macports/build/_opt_local_var_macports_sources_rsync.macports.org_macports_release_tarballs_ports_devel_luv
 /luv-luajit/work/build"

 /usr/bin/clang -Dlibluv_EXPORTS -I/opt/local/include
 -I/opt/local/include/luajit-2.1
 -I/opt/local/var/macports/build/_opt_local_var_macports_sources_rsync.macports.org_macports_release_tarballs_ports_devel_luv
 /luv-luajit/work/luv-1.45.0-0/deps/lua-compat-5.3/c-api -pipe -Os -DNDEBUG
 -I/opt/local/include
 -isysroot/Library/Developer/CommandLineTools/SDKs/MacOSX14.sdk -arch arm64
 -isysroot /Library/Developer/CommandLineTools/SDKs/MacOSX14.sdk -mmacosx-
 version-min=14.0 -fPIC -MD -MT CMakeFiles/libluv.dir/src/luv.c.o -MF
 CMakeFiles/libluv.dir/src/luv.c.o.d -o - -c
 /opt/local/var/macports/build/_opt_local_var_macports_sources_rsync.macports.org_macports_release_tarballs_ports_devel_luv
 /luv-luajit/work/luv-1.45.0-0/src/luv.c -E | awk '/extern luv_ctx_t\*
 luv_context\(lua_State\* L\) {/','/lua_type/'

 extern luv_ctx_t* luv_context(lua_State* L) {
   luv_ctx_t* ctx;
   lua_pushstring(L, luv_ctx_key);
   lua_rawget(L, (-1000000 - 1000));
   if ((lua_type(L, (-1)) == 0)) {
 }}}

 it can be seen that the macro expands to `(-1000000 - 1000)`.

 However, port `luajit` (that provides `libluajit-5.1.2.dylib`) and
 `ljamalg.c` are compiled against its own version of `lua.h`.

 By running preprocessor on `ljamalg.c` and peeking at the definition of
 `index2adr` function (when the segmentation fault occurs):

 {{{
 cd
 /opt/local/var/macports/build/_opt_local_var_macports_sources_rsync.macports.org_macports_release_tarballs_ports_lang_luajit/luajit/work
 /LuaJIT-43d0a19158ceabaa51b0462c1ebc97612b420a2e/src

 /opt/local/var/macports/build/_opt_local_var_macports_sources_rsync.macports.org_macports_release_tarballs_ports_lang_luajit/luajit/work/compwrap/cc/usr/bin/clang
 -O2 -fomit-frame-pointer -Wall  -Os -DLUAJIT_ENABLE_LUA52COMPAT
 -isysroot/Library/Developer/CommandLineTools/SDKs/MacOSX14.sdk -arch arm64
 -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -U_FORTIFY_SOURCE
 -DLUA_ROOT=\"/opt/local\" -DLUA_MULTILIB=\"lib\" -fno-stack-protector
 -DLUAJIT_UNWIND_EXTERNAL   -E -o - ljamalg.c | awk '/static TValue
 \*index2adr\(/,/} else {/'

 static TValue *index2adr(lua_State *L, int idx)
 {
   if (idx > 0) {
     TValue *o = L->base + (idx - 1);
     return o < L->top ? o : (&(((global_State *)(void
 *)(L->glref).ptr64))->nilnode.val);
   } else if (idx > (-10000)) {
     ((void)L);

     return L->top + idx;
   } else if (idx == (-10002)) {
     TValue *o = &(((global_State *)(void *)(L->glref).ptr64))->tmptv;
     settabV(L, o, ((GCtab *)((GCobj *)((L->env)).gcptr64)));
     return o;
   } else if (idx == (-10000)) {
     return (&(((global_State *)(void *)(L->glref).ptr64))->registrytv);
   } else
 }}}

 it can be seen that the macro expands to `(-10000)`.

 The segmentation fault occurs

 {{{
 (lldb) bt
 * thread #1, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS
 (code=1, address=0x800000000027)
   * frame #0: 0x0000000100c9db38
 libluajit-5.1.2.dylib`___lldb_unnamed_symbol507 + 48
     frame #1: 0x0000000100ca5ce8 libluajit-5.1.2.dylib`lua_rawget + 40
     frame #2: 0x00000001009ac364 libluv.1.dylib`luv_context + 44
     frame #3: 0x00000001009ac42c libluv.1.dylib`luv_set_loop + 24
     frame #4: 0x00000001001c33a0
 nvim`nlua_common_vim_init.llvm.13061164706051272520 + 572
     frame #5: 0x00000001001c2188 nvim`nlua_init + 528
     frame #6: 0x00000001001ccda8 nvim`main + 5024
     frame #7: 0x00000001889150e0 dyld`start + 2360
 }}}

 due to this mismatch since when executing `index2adr`
 (`___lldb_unnamed_symbol507` in `bt` output) instead of taking `else if
 (idx == LUA_REGISTRYINDEX)` branch the code path go to the `else` branch:

 {{{
 static TValue *index2adr(lua_State *L, int idx)
 {
   if (idx > 0) {
     TValue *o = L->base + (idx - 1);
     return o < L->top ? o : niltv(L);
   } else if (idx > LUA_REGISTRYINDEX) {
     lj_checkapi(idx != 0 && -idx <= L->top - L->base,
                 "bad stack slot %d", idx);
     return L->top + idx;
   } else if (idx == LUA_GLOBALSINDEX) {
     TValue *o = &G(L)->tmptv;
     settabV(L, o, tabref(L->env));
     return o;
   } else if (idx == LUA_REGISTRYINDEX) {
     return registry(L);
   } else {
     GCfunc *fn = curr_func(L);
     lj_checkapi(fn->c.gct == ~LJ_TFUNC && !isluafunc(fn),
                 "calling frame is not a C function");
     if (idx == LUA_ENVIRONINDEX) {
       TValue *o = &G(L)->tmptv;
       settabV(L, o, tabref(fn->c.env));
       return o;
     } else {
       idx = LUA_GLOBALSINDEX - idx;
       return idx <= fn->c.nupvalues ? &fn->c.upvalue[idx-1] : niltv(L);
     }
   }
 }
 }}}


 By uninstalling `lua` port (need to be forced since `lua-luarocks` still
 depends on `lua`) and re-installing `luv-luajit` port I could make the
 installation of `neovim` succeed.

 While looking into this, I also noticed that `lua51-lpeg` pulls down both
 `lua51` and `lua-luarocks` (which in turns pulls down `lua`) and I am not
 sure if this looks right:

 {{{
 port rdeps lua51-lpeg
 The following ports are dependencies of lua51-lpeg @1.1.0_0:
   lua-luarocks
     lua
       readline
         ncurses
     lua53-luarocks
       lua53
   lua51
 }}}


 Uninstalling `lua` is, obviously, not a proper solution here but I wanted
 to share this in case someone more familiar with MacPorts dependencies
 would able to pick it up from here.

-- 
Ticket URL: <https://trac.macports.org/ticket/68126#comment:34>
MacPorts <https://www.macports.org/>
Ports system for macOS


More information about the macports-tickets mailing list