nvim-treesitter / nvim-treesitter

Nvim Treesitter configurations and abstraction layer
Apache License 2.0
10.7k stars 894 forks source link

crash: segfault due to trying to free() an invalid pointer during TreeSitter HTML parsing #6665

Closed dkasak closed 5 months ago

dkasak commented 5 months ago

Describe the bug

A segfault occurs while editing HTML containing a <summary> tag.

To Reproduce

  1. Create HTML file with content: <summary></summary>
  2. Position cursor in between the two tags.
  3. Enter insert mode and start typing.
  4. A crash happens after the third character is input.

Expected behavior

There should be no crash.

Output of :checkhealth nvim-treesitter

==============================================================================
nvim-treesitter: require("nvim-treesitter.health").check()

Installation ~
- WARNING `tree-sitter` executable not found (parser generator, only needed for :TSInstallFromGrammar, not required for :TSInstall)
- OK `node` found v22.0.0 (only needed for :TSInstallFromGrammar)
- OK `git` executable found.
- OK `cc` executable found. Selected from { vim.NIL, "cc", "gcc", "clang", "cl", "zig" }
  Version: cc (GCC) 14.1.1 20240507
- OK Neovim was compiled with tree-sitter runtime ABI version 14 (required >=13). Parsers must be compatible with runtime ABI.

OS Info:
{
  machine = "x86_64",
  release = "6.9.1-arch1-1",
  sysname = "Linux",
  version = "#1 SMP PREEMPT_DYNAMIC Fri, 17 May 2024 16:56:38 +0000"
} ~

Parser/Features         H L F I J
  - bash                ✓ ✓ ✓ . ✓
  - c                   ✓ ✓ ✓ ✓ ✓
  - cpp                 ✓ ✓ ✓ ✓ ✓
  - css                 ✓ . ✓ ✓ ✓
  - dockerfile          ✓ . . . ✓
  - haskell             ✓ . ✓ . ✓
  - html                ✓ ✓ ✓ ✓ ✓
  - javascript          ✓ ✓ ✓ ✓ ✓
  - jq                  ✓ ✓ . . ✓
  - kotlin              ✓ ✓ ✓ . ✓
  - latex               ✓ . ✓ . ✓
  - lua                 ✓ ✓ ✓ ✓ ✓
  - markdown            ✓ . ✓ ✓ ✓
  - markdown_inline     ✓ . . . ✓
  - mermaid             ✓ . . . .
  - python              ✓ ✓ ✓ ✓ ✓
  - query               ✓ ✓ ✓ ✓ ✓
  - rust                ✓ ✓ ✓ ✓ ✓
  - toml                ✓ ✓ ✓ ✓ ✓
  - typescript          ✓ ✓ ✓ ✓ ✓
  - vimdoc              ✓ . . . ✓
  - yaml                ✓ ✓ ✓ ✓ ✓

  Legend: H[ighlight], L[ocals], F[olds], I[ndents], In[j]ections
         +) multiple parsers found, only one will be used
         x) errors found in the query, try to run :TSUpdate {lang} ~

Output of nvim --version

NVIM v0.10.0
Build type: Release
LuaJIT 2.1.1713773202
Run "nvim -V1 -v" for more info

Additional context

Stack trace:

#0  0x00007d7aa4f3ed55 in __GI___libc_free (mem=0x2e42475f6e652f65) at malloc.c:3375
#1  0x00007d7aa4dd0af7 in tree_sitter_html_external_scanner_destroy () from /home/dkasak/.local/share/nvim/lazy/nvim-treesitter/parser/html.so
#2  0x00007d7aa52810c6 in ts_parser__external_scanner_destroy (self=0x62e143d60330) at lib/src/parser.c:383
#3  ts_parser_reset (self=self@entry=0x62e143d60330) at lib/src/parser.c:1970
#4  0x00007d7aa52817b5 in ts_parser_parse (self=self@entry=0x62e143d60330, old_tree=old_tree@entry=0x62e143cc87e0, input=...) at lib/src/parser.c:2114
#5  0x000062e135c18735 in parser_parse (L=0x7d7aa5315380) at /usr/src/debug/neovim/neovim-0.10.0/src/nvim/lua/treesitter.c:359
#6  0x00007d7aa51d9ef6 in lj_BC_FUNCC () at buildvm_x86.dasc:857
#7  0x00007d7aa51ecd43 in lua_pcall (L=L@entry=0x7d7aa5315380, nargs=nargs@entry=5, nresults=nresults@entry=1, errfunc=errfunc@entry=-7) at /usr/src/debug/luajit/LuaJIT-5790d253972c9d78a0c2aece527eda5b134bbbf7/src/lj_api.c:1122
#8  0x000062e135e39e8e in nlua_pcall (nresults=1, lstate=0x7d7aa5315380, nargs=5) at /usr/src/debug/neovim/neovim-0.10.0/src/nvim/lua/executor.c:173
#9  nlua_call_ref.constprop.0 (ref=<optimized out>, name=name@entry=0x62e135e70026 "win", args=..., err=err@entry=0x7ffd099d3770, arena=<optimized out>, mode=<optimized out>)
    at /usr/src/debug/neovim/neovim-0.10.0/src/nvim/lua/executor.c:1606
#10 0x000062e135e43e81 in decor_provider_invoke.constprop.0 (provider_idx=provider_idx@entry=4, name=name@entry=0x62e135e70026 "win", ref=<optimized out>, args=..., default_true=true)
    at /usr/src/debug/neovim/neovim-0.10.0/src/nvim/decoration_provider.c:51
#11 0x000062e135ab148b in decor_providers_invoke_win (wp=0x62e1438d2970) at /usr/src/debug/neovim/neovim-0.10.0/src/nvim/decoration_provider.c:144
#12 0x000062e135ad2293 in win_update (wp=0x62e1438d2970) at /usr/src/debug/neovim/neovim-0.10.0/src/nvim/drawscreen.c:1512
#13 0x000062e135acdece in update_screen () at /usr/src/debug/neovim/neovim-0.10.0/src/nvim/drawscreen.c:647
#14 0x000062e135ae20ad in ins_redraw (ready=<optimized out>) at /usr/src/debug/neovim/neovim-0.10.0/src/nvim/edit.c:1395
#15 0x000062e135ad8006 in ins_redraw (ready=true) at /usr/src/debug/neovim/neovim-0.10.0/src/nvim/getchar.c:1841
#16 insert_check (state=0x7ffd099d3db0) at /usr/src/debug/neovim/neovim-0.10.0/src/nvim/edit.c:499
#17 0x000062e135d7ed93 in state_enter (s=0x7ffd099d3db0) at /usr/src/debug/neovim/neovim-0.10.0/src/nvim/state.c:40
#18 0x000062e135e346e5 in insert_enter.constprop.0 (s=s@entry=0x7ffd099d3db0) at /usr/src/debug/neovim/neovim-0.10.0/src/nvim/edit.c:345
#19 0x000062e135ad5cc3 in edit (cmdchar=<optimized out>, startln=<optimized out>, count=<optimized out>) at /usr/src/debug/neovim/neovim-0.10.0/src/nvim/edit.c:1294
#20 0x000062e135c9e72e in op_change (oap=0x7ffd099d4168) at /usr/src/debug/neovim/neovim-0.10.0/src/nvim/ops.c:2454
#21 0x000062e135cab2d5 in do_pending_operator (cap=0x7ffd099d41c0, old_col=9, gui_yank=false) at /usr/src/debug/neovim/neovim-0.10.0/src/nvim/ops.c:6172
#22 0x000062e135c86eef in normal_finish_command (s=0x7ffd099d4150) at /usr/src/debug/neovim/neovim-0.10.0/src/nvim/normal.c:972
#23 normal_execute (state=0x7ffd099d4150, key=<optimized out>) at /usr/src/debug/neovim/neovim-0.10.0/src/nvim/normal.c:1232
#24 0x000062e135d7ee8d in state_enter (s=0x7ffd099d4150) at /usr/src/debug/neovim/neovim-0.10.0/src/nvim/state.c:101
#25 0x000062e135c842da in normal_enter (cmdwin=<optimized out>, noexmode=<optimized out>) at /usr/src/debug/neovim/neovim-0.10.0/src/nvim/normal.c:518
#26 0x000062e135a23aef in main (argc=<optimized out>, argv=<optimized out>) at /usr/src/debug/neovim/neovim-0.10.0/src/nvim/main.c:664

Source code:

3370    
3371     int err = errno;
3372    
3373     p = mem2chunk (mem);
3374    
3375     if (chunk_is_mmapped (p))                       /* release mmapped memory. */       <=== crash happens here
3376       {
3377         /* See if the dynamic brk/mmap threshold needs adjusting.
3378        Dumped fake mmapped chunks do not affect the threshold.  */
3379         if (!mp_.no_dyn_threshold

Assembly analysis:

(gdb) x/5i $rip
=> 0x7d7aa4f3ed55 <__GI___libc_free+37>:    mov    -0x8(%rdi),%rax
   0x7d7aa4f3ed59 <__GI___libc_free+41>:    mov    %fs:(%rbx),%r12d
   0x7d7aa4f3ed5d <__GI___libc_free+45>:    test   $0x2,%al
   0x7d7aa4f3ed5f <__GI___libc_free+47>:    jne    0x7d7aa4f3edc0 <__GI___libc_free+144>
   0x7d7aa4f3ed61 <__GI___libc_free+49>:    mov    0x13df38(%rip),%rdx        # 0x7d7aa507cca0
(gdb) p $rdi
$1 = 3333305149407178597
clason commented 5 months ago

Please report that at the tree-sitter-html repo.