Subject: bug#60237: 30.0.50; tree sitter core dumps when I edebug view a node

From: Po Lu <[email-masked]>
Date: Sat, 25 Feb 2023 15:13:44 +0800

Yuan Fu <[email-masked]> writes:

> * thread #1, queue = 'com.apple.main-thread', stop reason = EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0)
>     frame #0: 0x0000000100250f3d emacs`ASIZE(array=0x00000001a1889245) at lisp.h:1768:3
>    1765	ASIZE (Lisp_Object array)
>    1766	{
>    1767	  ptrdiff_t size = XVECTOR (array)->header.size;
> -> 1768	  eassume (0 <= size);
>    1769	  return size;
>    1770	}
>    1771

This is a bug inside the profiler: if it is trying to hook into xmalloc,
it should not call anything that can call ASIZE, because GC modifies the
mark bits inside the vector header, which happen to be stored in the
`size' field, and GC has been able to call xmalloc ever since the mark
stack stuff was installed.

Since you assume 0 <= size, LLVM is generating one of its favorite
instructions, ud2, in response to a situation you told the compiler
would never happen.  Make sure that situation doesn't happen!!

> Target 0: (emacs) stopped.
> (lldb) bt
> * thread #1, queue = 'com.apple.main-thread', stop reason = EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0)
>   * frame #0: 0x0000000100250f3d emacs`ASIZE(array=0x00000001a1889245) at lisp.h:1768:3
>     frame #1: 0x0000000100250e5e emacs`get_backtrace(array=0x00000001a1889245) at eval.c:4193:28
>     frame #2: 0x00000001003001ce emacs`record_backtrace(log=0x00000001a1887d68, count=64) at profiler.c:162:3
>     frame #3: 0x000000010030016d emacs`malloc_probe(size=64) at profiler.c:509:3
>     frame #4: 0x0000000100204e6d emacs`xmalloc(size=64) at alloc.c:760:3
>     frame #5: 0x0000000100e6c0c9 libtree-sitter.0.dylib`ts_subtree_release + 158
>     frame #6: 0x0000000100e6f004 libtree-sitter.0.dylib`ts_tree_delete + 44
>     frame #7: 0x0000000100307379 emacs`treesit_delete_parser(lisp_parser=0x00000001a2c0f0e0) at treesit.c:1182:3
>     frame #8: 0x0000000100212c1b emacs`cleanup_vector(vector=0x00000001a2c0f0e0) at alloc.c:3179:5
>     frame #9: 0x00000001002124c9 emacs`sweep_vectors at alloc.c:3254:5
>     frame #10: 0x000000010020c777 emacs`gc_sweep at alloc.c:7430:3
>     frame #11: 0x000000010020bb67 emacs`garbage_collect at alloc.c:6262:3
>     frame #12: 0x000000010020b706 emacs`maybe_garbage_collect at alloc.c:6107:5
>     frame #13: 0x00000001002b4bea emacs`maybe_gc at lisp.h:5591:5

BTW, where do you see GC being called from treesit_delete_parser?  What
I see is a bug in the profiler; it should use some other data structure
to store its backtraces, when its xmalloc hook is called.

GC has historically never called xmalloc, so the profiler will likely
crash upon growing the mark stack as well.  I guess another important
question is why ts_delete_parser is calling xmalloc.