nvim-treesitter / nvim-treesitter

Nvim Treesitter configurations and abstraction layer
Apache License 2.0
10.93k stars 910 forks source link

Coredump with prisma files #2979

Closed mikehaertl closed 2 years ago

mikehaertl commented 2 years ago

Describe the bug

When I edit prisma files neovim sometimes crashes with a core dump.

To Reproduce

  1. Edit a prisma file (see below for my example)
  2. Yank line 24
  3. Paste the line at the end of the file
// This is your Prisma schema file,
// learn more about it in the docs: https://pris.ly/d/prisma-schema

datasource db {
  provider = "sqlite"
  url      = "file:./dev.db"
}

generator client {
  provider = "prisma-client-js"
}

model Link {
  id          Int       @id @default(autoincrement())
  createdAt   DateTime  @default(now())
  description String
  url         String
  postedBy    User?     @relation(fields: [postedById], references: [id])
  postedById  Int?
  votes       Vote[]
}

model User {
  id          Int       @id @default(autoincrement())
  name        String
  email       String    @unique
  password    String
  links       Link[]
  votes       Vote[]
}

Expected behavior

No coredump

Output of :checkhealth nvim-treesitter

nvim-treesitter: require("nvim-treesitter.health").check()
========================================================================
## Installation
  - OK: `tree-sitter` found 0.20.4 (714bfd47a744ab44b904375c177a24c0614ef49c) (parser generator, only needed for :TSInstallFromGrammar)
  - OK: `node` found v16.15.0 (only needed for :TSInstallFromGrammar)
  - OK: `git` executable found.
  - OK: `cc` executable found. Selected from { vim.NIL, "cc", "gcc", "clang", "cl", "zig" }
    Version: cc (Ubuntu 9.4.0-1ubuntu1~20.04.1) 9.4.0
  - OK: Neovim was compiled with tree-sitter runtime ABI version 14 (required >=13). Parsers must be compatible with runtime ABI.

## Parser/Features H L F I J
  - gomod          ✓ . . . ✓ 
  - css            ✓ . ✓ ✓ ✓ 
  - scss           ✓ . . ✓ . 
  - cpp            ✓ ✓ ✓ ✓ ✓ 
  - yang           ✓ . ✓ ✓ . 
  - typescript     ✓ ✓ ✓ ✓ ✓ 
  - ninja          ✓ . ✓ ✓ . 
  - nix            ✓ ✓ ✓ . ✓ 
  - javascript     ✓ ✓ ✓ ✓ ✓ 
  - python         ✓ ✓ ✓ ✓ ✓ 
  - dart           ✓ ✓ . ✓ ✓ 
  - vue            ✓ . ✓ ✓ ✓ 
  - rst            ✓ ✓ . . ✓ 
  - fennel         ✓ ✓ . . ✓ 
  - teal           ✓ ✓ ✓ ✓ ✓ 
  - ql             ✓ ✓ . ✓ ✓ 
  - astro          ✓ ✓ ✓ ✓ ✓ 
  - elvish         ✓ . . . ✓ 
  - pascal         ✓ ✓ ✓ ✓ ✓ 
  - cooklang       ✓ . . . . 
  - rasi           ✓ ✓ ✓ ✓ . 
  - solidity       ✓ . . . . 
  - lalrpop        ✓ ✓ . . . 
  - vala           ✓ . . . . 
  - json           ✓ ✓ ✓ ✓ . 
  - vim            ✓ ✓ . . ✓ 
  - norg           . . . . . 
  - sparql         ✓ ✓ ✓ ✓ ✓ 
  - fish           ✓ ✓ ✓ ✓ ✓ 
  - gdscript       ✓ ✓ . ✓ ✓ 
  - make           ✓ . . . ✓ 
  - comment        ✓ . . . . 
  - http           ✓ . . . ✓ 
  - godot_resource ✓ ✓ ✓ . . 
  - kotlin         ✓ ✓ ✓ . ✓ 
  - bash           ✓ ✓ ✓ . ✓ 
  - graphql        ✓ . . ✓ ✓ 
  - html           ✓ ✓ ✓ ✓ ✓ 
  - dockerfile     ✓ . . . ✓ 
  - tsx            ✓ ✓ ✓ ✓ ✓ 
  - devicetree     ✓ ✓ ✓ ✓ ✓ 
  - hcl            ✓ . ✓ ✓ ✓ 
  - jsdoc          ✓ . . . . 
  - glimmer        ✓ . . . . 
  - perl           ✓ . ✓ . . 
  - erlang         . . . . . 
  - ruby           ✓ ✓ ✓ ✓ ✓ 
  - rust           ✓ ✓ ✓ ✓ ✓ 
  - scheme         ✓ . ✓ . ✓ 
  - toml           ✓ ✓ ✓ ✓ ✓ 
  - go             ✓ ✓ ✓ ✓ ✓ 
  - svelte         ✓ . ✓ ✓ ✓ 
  - gleam          ✓ ✓ ✓ ✓ ✓ 
  - beancount      ✓ . ✓ . . 
  - surface        ✓ . ✓ ✓ ✓ 
  - bibtex         ✓ . ✓ ✓ . 
  - eex            ✓ . . . ✓ 
  - zig            ✓ . ✓ ✓ ✓ 
  - heex           ✓ ✓ ✓ ✓ ✓ 
  - r              x x . x x 
  - ocaml          ✓ ✓ ✓ . ✓ 
  - latex          ✓ . ✓ . ✓ 
  - json5          ✓ . . . ✓ 
  - ocaml_interface✓ ✓ ✓ . ✓ 
  - help           ✓ . . . . 
  - cmake          ✓ . ✓ . . 
  - rego           ✓ . . . ✓ 
  - pioasm         ✓ . . . ✓ 
  - hjson          ✓ ✓ ✓ ✓ ✓ 
  - hocon          ✓ . . . ✓ 
  - c_sharp        ✓ ✓ ✓ . ✓ 
  - markdown       ✓ . ✓ . ✓ 
  - llvm           ✓ . . . . 
  - turtle         ✓ ✓ ✓ ✓ ✓ 
  - commonlisp     ✓ ✓ ✓ . . 
  - regex          ✓ . . . . 
  - c              ✓ ✓ ✓ ✓ ✓ 
  - prisma         ✓ . . . . 
  - query          ✓ ✓ ✓ ✓ ✓ 
  - phpdoc         ✓ . . . . 
  - scala          ✓ . ✓ . ✓ 
  - elixir         ✓ ✓ ✓ ✓ ✓ 
  - supercollider  ✓ ✓ ✓ ✓ ✓ 
  - java           ✓ ✓ . ✓ ✓ 
  - glsl           ✓ ✓ ✓ ✓ ✓ 
  - php            ✓ ✓ ✓ ✓ ✓ 
  - lua            ✓ ✓ ✓ ✓ ✓ 
  - julia          ✓ ✓ ✓ ✓ ✓ 
  - gowork         ✓ . . . ✓ 
  - dot            ✓ . . . ✓ 
  - fusion         ✓ ✓ ✓ ✓ . 
  - tlaplus        ✓ ✓ ✓ . ✓ 
  - ocamllex       ✓ . . . ✓ 
  - ledger         ✓ . ✓ ✓ ✓ 
  - cuda           ✓ ✓ ✓ ✓ ✓ 
  - clojure        ✓ ✓ ✓ . ✓ 
  - jsonc          ✓ ✓ ✓ ✓ ✓ 
  - pug            ✓ . . . ✓ 
  - 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}

## The following errors have been detected:
  - ERROR: r(highlights): Failed to load parser: uv_dlopen: /home/mike/.local/share/nvim/plugged/nvim-treesitter/parser/r.so: undefined symbol: tree_sitter_r_external_scanner_create
    r(highlights) is concatenated from the following files:
    | [ERROR]:"/home/mike/.local/share/nvim/plugged/nvim-treesitter/queries/r/highlights.scm", failed to load: Failed to load parser: uv_dlopen: /home/mike/.local/share/nvim/plugged/nvim-treesitter/parser/r.so: undefined symbol: tree_sitter_r_external_scanner_create
  - ERROR: r(locals): Failed to load parser: uv_dlopen: /home/mike/.local/share/nvim/plugged/nvim-treesitter/parser/r.so: undefined symbol: tree_sitter_r_external_scanner_create
    r(locals) is concatenated from the following files:
    | [ERROR]:"/home/mike/.local/share/nvim/plugged/nvim-treesitter/queries/r/locals.scm", failed to load: Failed to load parser: uv_dlopen: /home/mike/.local/share/nvim/plugged/nvim-treesitter/parser/r.so: undefined symbol: tree_sitter_r_external_scanner_create
  - ERROR: r(indents): Failed to load parser: uv_dlopen: /home/mike/.local/share/nvim/plugged/nvim-treesitter/parser/r.so: undefined symbol: tree_sitter_r_external_scanner_create
    r(indents) is concatenated from the following files:
    | [ERROR]:"/home/mike/.local/share/nvim/plugged/nvim-treesitter/queries/r/indents.scm", failed to load: Failed to load parser: uv_dlopen: /home/mike/.local/share/nvim/plugged/nvim-treesitter/parser/r.so: undefined symbol: tree_sitter_r_external_scanner_create
  - ERROR: r(injections): Failed to load parser: uv_dlopen: /home/mike/.local/share/nvim/plugged/nvim-treesitter/parser/r.so: undefined symbol: tree_sitter_r_external_scanner_create
    r(injections) is concatenated from the following files:
    | [ERROR]:"/home/mike/.local/share/nvim/plugged/nvim-treesitter/queries/r/injections.scm", failed to load: Failed to load parser: uv_dlopen: /home/mike/.local/share/nvim/plugged/nvim-treesitter/parser/r.so: undefined symbol: tree_sitter_r_external_scanner_create

Output of nvim --version

NVIM v0.7.0
Build type: RelWithDebInfo
LuaJIT 2.1.0-beta3
Compilation: /usr/bin/cc -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=1 -DNVIM_TS_HAS_SET_MATCH_LIMIT -DNVIM_TS_HAS_SET_ALLOCATOR -O2 -g -Og -g -Wall -Wextra -pedantic -Wno-unused-parameter -Wstrict-prototypes -std=gnu99 -Wshadow -Wconversion -Wdouble-promotion -Wmissing-noreturn -Wmissing-format-attribute -Wmissing-prototypes -Wimplicit-fallthrough -Wsuggest-attribute=pure -Wsuggest-attribute=const -Wsuggest-attribute=malloc -Wsuggest-attribute=cold -Wvla -fstack-protector-strong -fno-common -fdiagnostics-color=always -DINCLUDE_GENERATED_DECLARATIONS -D_GNU_SOURCE -DNVIM_MSGPACK_HAS_FLOAT32 -DNVIM_UNIBI_HAS_VAR_FROM -DMIN_LOG_LEVEL=3 -I/home/mike/repos/github/neovim/build/config -I/home/mike/repos/github/neovim/src -I/home/mike/repos/github/neovim/.deps/usr/include -I/usr/include -I/home/mike/repos/github/neovim/build/src/nvim/auto -I/home/mike/repos/github/neovim/build/include
Übersetzt von mike@Nilar

Features: +acl +iconv +tui
See ":help feature-compile"

          System-vimrc-Datei: "$VIM/sysinit.vim"
     Voreinstellung für $VIM: "/usr/local/share/nvim"

Run :checkhealth for more info

Additional context

I've run gdb on the coredump file and got this backtrace:

Reading symbols from /usr/local/bin/nvim...
[New LWP 700401]
[New LWP 700402]
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
Core was generated by `vi'.
Program terminated with signal SIGSEGV, Segmentation fault.
#0  0x0000558940d16480 in ts_parser_parse ()
[Current thread is 1 (Thread 0x7f3b8d681740 (LWP 700401))]
(gdb) bt
#0  0x0000558940d16480 in ts_parser_parse ()
#1  0x0000558940b97a8c in parser_parse (L=0x7f3b8da17380) at ../src/nvim/lua/treesitter.c:378
#2  0x0000558940d4c0c6 in lj_BC_FUNCC ()
#3  0x0000558940d393f9 in lua_pcall (L=L@entry=0x7f3b8da17380, nargs=nargs@entry=2, nresults=nresults@entry=1, errfunc=errfunc@entry=-4) at lj_api.c:1116
#4  0x0000558940b97fc5 in nlua_pcall (lstate=lstate@entry=0x7f3b8da17380, nargs=nargs@entry=2, nresults=nresults@entry=1) at ../src/nvim/lua/executor.c:129
#5  0x0000558940b9d4d2 in nlua_call_ref (ref=<optimized out>, name=<optimized out>, args=..., retval=<optimized out>, err=0x7fff2b1f0880) at ../src/nvim/lua/executor.c:1366
#6  0x0000558940c60097 in decor_provider_invoke (ns_id=9, name=name@entry=0x558940de96c9 "buf", ref=<optimized out>, args=..., default_true=default_true@entry=true, 
    perr=perr@entry=0x558940ee3d28 <provider_err>) at ../src/nvim/decoration_provider.c:26
#7  0x0000558940c6033e in decor_providers_invoke_buf (buf=0x558941769b60, providers=0x7fff2b1f09a0, err=0x558940ee3d28 <provider_err>) at ../src/nvim/decoration_provider.c:156
#8  0x0000558940aef710 in update_screen (type=<optimized out>) at ../src/nvim/screen.c:551
#9  0x0000558940b5ea51 in normal_redraw (s=s@entry=0x7fff2b1f0a80) at ../src/nvim/normal.c:1290
#10 0x0000558940b5f30c in normal_check (state=0x7fff2b1f0a80) at ../src/nvim/normal.c:1381
#11 0x0000558940aa84dd in state_enter (s=0x7fff2b1f0a80) at ../src/nvim/state.c:31
#12 0x0000558940b605b5 in normal_enter (cmdwin=<optimized out>, noexmode=<optimized out>) at ../src/nvim/normal.c:463
#13 0x0000558940b96f47 in main (argc=<optimized out>, argv=<optimized out>) at ../src/nvim/main.c:574
kyazdani42 commented 2 years ago

Looks like a bug in the prisma parser. Should this issue be upstreamed there ?

mikehaertl commented 2 years ago

Ok, agreed. I'll open another issue there. The issue here can then probably be closed?

kyazdani42 commented 2 years ago

let's leave this open for now, we'll need to update the parser once the fix is done.

mikehaertl commented 2 years ago

@kyazdani42 I wondered why the backtrace does not include any pointers to the parser file. I tried to recompile the parser with debug symbols like this:

cc -g -o /home/mike/.local/share/nvim/plugged/nvim-treesitter/parser/prisma.so -I./src src/parser.c -shared -Os -lstdc++

But still there's no trace of prisma's parser in the backtrace.

Do you happen to have some hints how I could further boil this down to the offending line in the parser?

kyazdani42 commented 2 years ago

I'm not too sure how to go about that, but i know there is a tool for fuzzying the parser. i know @theHamsta will have more info on this :)

theHamsta commented 2 years ago

Prisma doesn't use a hand written parser. Bugs in the generated code are very rare but you can try out the fuzzing tool. instructions here https://github.com/ikatyang/tree-sitter-markdown/issues/14

I would try to compile the parser with -O0 instead of -Os

mikehaertl commented 2 years ago

@theHamsta Thanks. I tried the recipe from the comment you linked but it failed at the ./script/build-fuzzer step:

[mike@Nilar tree-sitter]$ ./script/build-fuzzers 
cc -fsanitize=fuzzer,address,undefined -std=gnu99 -fPIC -Ilib/src -Ilib/include   -c -o lib/src/tree_cursor.o lib/src/tree_cursor.c
cc: error: unrecognized argument to ‘-fsanitize=’ option: ‘fuzzer’
make: *** [<eingebaut>: lib/src/tree_cursor.o] Fehler 1

I admit that I don't really understand what I'm doing here and how fuzzing works. I couldn't make much sense of the example fuzzer output in your comment either.

I also tried to compile the parser with -o0 but it didn't make any difference in the back trace.

If you have any further hints how to debug this problem maybe you want to comment on the tree-sitter-prisma issue linked above?

theHamsta commented 2 years ago

@mikehaertl the above script expects CC to be clang (not GCC) to be able to use the memory sanitizer option. Llvm has a library called libfuzzer and clang can use it to construct inputs that cleverly try to run all the code paths of the parser. Clang will need to compile the binary with special flags, also with memory sanitizer which will add additional checks to detect segfaults, usage of uninitialized memory and similar issues.

mikehaertl commented 2 years ago

@theHamsta I see, thanks for the explanation.

The upstream issue meanwhile has been fixed. I don't remeber if the version has to be pushed in this repo or if this happens automatically.

clason commented 2 years ago

The upstream issue meanwhile has been fixed. I don't remeber if the version has to be pushed in this repo or if this happens automatically.

This happens automatically (well, not fully; I still have to press a few buttons.)

If the fix was not made in the last few minutes, it's now pulled in by nvim-treesitter: https://github.com/nvim-treesitter/nvim-treesitter/commit/7a22d9280119b3e57332ddd855583b609e809ce7

mikehaertl commented 2 years ago

Closing this as the fix seems to work fine.