Go into Vim's own src directory, open Vim with vim --clean, and run :vimgrep /\%v/ *'.
Result:
Vim: Caught deadly signal SEGV
Press ENTER or type command to continueVim: Finished.
Segmentation fault
No crash.
8.2.4677
Linux
No response
—
Reply to this email directly, view it on GitHub.
You are receiving this because you are subscribed to this thread.![]()
I can reproduce it with vim-8.2.4681:
$ cd vim/src
$ git clean -dfx
$ CC=clang-13 ./configure --with-features=huge --enable-gui=none
$ make -j8
# The following command takes a while and then crashes:
$ valgrind ./vim --clean -c "vimgrep /\%v/ *" 2> valgrind.log
Vim: Caught deadly signal SEGV
Vim: Finished.
Segmentation fault (core dumped)
$ cat valgrind.log
==5579== Memcheck, a memory error detector
==5579== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==5579== Using Valgrind-3.17.0.GIT and LibVEX; rerun with -h for copyright info
==5579== Command: ./vim --clean -c vimgrep\ /\\%v/\ *
==5579==
==5579== Invalid read of size 4
==5579== at 0x53A144: vim_regexec_multi (regexp.c:2852)
==5579== by 0x532A05: vgr_match_buflines (quickfix.c:5991)
==5579== by 0x532A05: vgr_process_files (quickfix.c:6274)
==5579== by 0x532A05: ex_vimgrep (quickfix.c:6398)
==5579== by 0x477485: do_one_cmd (ex_docmd.c:2567)
==5579== by 0x477485: do_cmdline (ex_docmd.c:993)
==5579== by 0x64C04C: exe_commands (main.c:3080)
==5579== by 0x64C04C: vim_main2 (main.c:772)
==5579== by 0x64B016: main (main.c:424)
==5579== Address 0x14 is not stack'd, malloc'd or (recently) free'd
==5579==
Press ENTER or type command to continue
==5579==
==5579== Process terminating with default action of signal 11 (SIGSEGV): dumping core
==5579== at 0x6AAC177: kill (syscall-template.S:78)
==5579== by 0x51B319: mch_exit (os_unix.c:3495)
==5579== by 0x64C5A2: getout (main.c:1710)
==5579== by 0x6AABF0F: ??? (in /lib/x86_64-linux-gnu/libc-2.27.so)
==5579== by 0x53A143: vim_regexec_multi (regexp.c:2852)
==5579== by 0x532A05: vgr_match_buflines (quickfix.c:5991)
==5579== by 0x532A05: vgr_process_files (quickfix.c:6274)
==5579== by 0x532A05: ex_vimgrep (quickfix.c:6398)
==5579== by 0x477485: do_one_cmd (ex_docmd.c:2567)
==5579== by 0x477485: do_cmdline (ex_docmd.c:993)
==5579== by 0x64C04C: exe_commands (main.c:3080)
==5579== by 0x64C04C: vim_main2 (main.c:772)
==5579== by 0x64B016: main (main.c:424)
==5579==
==5579== HEAP SUMMARY:
==5579== in use at exit: 21,999,259 bytes in 30,030 blocks
==5579== total heap usage: 1,660,636 allocs, 1,630,606 frees, 12,149,596,139 bytes allocated
==5579==
==5579== LEAK SUMMARY:
==5579== definitely lost: 6,080 bytes in 5 blocks
==5579== indirectly lost: 39 bytes in 2 blocks
==5579== possibly lost: 67,045 bytes in 2,276 blocks
==5579== still reachable: 21,926,095 bytes in 27,747 blocks
==5579== suppressed: 0 bytes in 0 blocks
==5579== Rerun with --leak-check=full to see details of leaked memory
==5579==
==5579== For lists of detected and suppressed errors, rerun with: -s
==5579== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
—
Reply to this email directly, view it on GitHub.
You are receiving this because you are subscribed to this thread.![]()
This happens, because vim_regex_multi() will run into this state here:
https://github.com/vim/vim/blob/15f74fab653a784548d5d966644926b47ba2cfa7/src/regexp.c#L2869-L2902
So basically, Vim will try to switch from the NFA regexp engine to the backtracking regexp engine. However, when compiling the new regengine, it fails, because \%v does not seem to be valid for the backtracking engine:
https://github.com/vim/vim/blob/15f74fab653a784548d5d966644926b47ba2cfa7/src/regexp.c#L2888
and so later vim will segfault in vim_regex_multi() when trying to access re_in_use:
https://github.com/vim/vim/blob/15f74fab653a784548d5d966644926b47ba2cfa7/src/regexp.c#L2852
because regprog is NULL.
It looks like this pattern \%v is compiled for the NFA engine and fails only after finishing searching, while when using the backtracking engine, it fails when compiling the pattern.
This patch avoids the segfault. Not sure if this is correct:
diff --git a/src/regexp.c b/src/regexp.c index 110d76d04..f6da6d39e 100644 --- a/src/regexp.c +++ b/src/regexp.c @@ -2890,6 +2890,16 @@ vim_regexec_multi( reg_do_extmatch = 0; #endif + if (rmp->regprog == NULL) + { + // compiling the pattern failed, avoid regprog becoming NULL + // and causing a segfault later on. + // So compile it again with the NFA engine. Compiling worked before, + // so hopefully it compiles again + p_re = NFA_ENGINE; + rmp->regprog = vim_regcomp(pat, re_flags); + siemsg("INTERNAL: compiling the pattern failed with backtracking engine"); + } if (rmp->regprog != NULL) { rmp->regprog->re_in_use = TRUE;
—
Reply to this email directly, view it on GitHub.
You are receiving this because you are subscribed to this thread.![]()
BTW: Here is the backtrace of emsg_core() when searching for \%v for NFA:
#0 emsg_core (s=0x619000000a80 "E486: Pattern not found: \\%v") at message.c:639
#1 0x000055555743e882 in semsg (s=0x555558c6f1a0 <e_pattern_not_found_str> "E486: Pattern not found: %s") at message.c:813
#2 0x0000555556f2c111 in searchit (win=0x625000002900, buf=0x625000005100, pos=0x7fffffffd790, end_pos=0x0, dir=1, pat=0x60b000004030 "\\%v", count=0, options=12, pat_use=2, extra_arg=0x7fffffffd910) at search.c:1148
#3 0x0000555556f2ec3b in do_search (oap=0x7fffffffdbf0, dirc=47, search_delim=47, pat=0x60b000004033 "", count=1, options=542, sia=0x7fffffffd910) at search.c:1565
#4 0x0000555556cb696f in normal_search (cap=0x7fffffffdad0, dir=47, pat=0x60b000004030 "\\%v", opt=512, wrapped=0x0) at normal.c:4200
#5 0x0000555556cb5d58 in nv_search (cap=0x7fffffffdad0) at normal.c:4151
#6 0x0000555556c95edb in normal_cmd (oap=0x7fffffffdbf0, toplevel=1) at normal.c:930
#7 0x0000555557420de0 in main_loop (cmdwin=0, noexmode=0) at main.c:1500
#8 0x000055555741f0d9 in vim_main2 () at main.c:877
#9 0x000055555741e59b in main (argc=2, argv=0x7fffffffde48) at main.c:424
Note: it fails ins searchit()
and here with the backtracing engine:
(gdb) bt
#0 emsg_core (s=0x619000000a80 "E71: Invalid character after \\%") at message.c:639
#1 0x000055555743e882 in semsg (s=0x555558c676c0 <e_invalid_character_after_str> "E71: Invalid character after %s%%") at message.c:813
#2 0x0000555556e3ec2b in regatom (flagp=0x7fffffffcf80) at regexp_bt.c:1699
#3 0x0000555556e41306 in regpiece (flagp=0x7fffffffd060) at regexp_bt.c:2072
#4 0x0000555556e42241 in regconcat (flagp=0x7fffffffd110) at regexp_bt.c:2258
#5 0x0000555556e42577 in regbranch (flagp=0x7fffffffd1c0) at regexp_bt.c:2294
#6 0x0000555556e42b13 in reg (paren=0, flagp=0x7fffffffd280) at regexp_bt.c:2371
#7 0x0000555556e435e8 in bt_regcomp (expr=0x60b000004240 "\\%v", re_flags=1) at regexp_bt.c:2476
#8 0x0000555556ec5312 in vim_regcomp (expr_arg=0x60b000004240 "\\%v", re_flags=1) at regexp.c:2616
#9 0x0000555556f25587 in search_regcomp (pat=0x60b000004240 "\\%v", pat_save=0, pat_use=2, options=0, regmatch=0x7fffffffd4b0) at search.c:187
#10 0x0000555556f28cfa in searchit (win=0x625000002900, buf=0x625000005100, pos=0x7fffffffd790, end_pos=0x0, dir=1, pat=0x60b000004240 "\\%v", count=1, options=12, pat_use=2, extra_arg=0x7fffffffd910) at search.c:675
#11 0x0000555556f2ec3b in do_search (oap=0x7fffffffdbf0, dirc=47, search_delim=47, pat=0x60b000004243 "", count=1, options=542, sia=0x7fffffffd910) at search.c:1565
#12 0x0000555556cb696f in normal_search (cap=0x7fffffffdad0, dir=47, pat=0x60b000004240 "\\%v", opt=512, wrapped=0x0) at normal.c:4200
#13 0x0000555556cb5d58 in nv_search (cap=0x7fffffffdad0) at normal.c:4151
#14 0x0000555556c95edb in normal_cmd (oap=0x7fffffffdbf0, toplevel=1) at normal.c:930
#15 0x0000555557420de0 in main_loop (cmdwin=0, noexmode=0) at main.c:1500
#16 0x000055555741f0d9 in vim_main2 () at main.c:877
#17 0x000055555741e59b in main (argc=2, argv=0x7fffffffde48) at main.c:424
Note: it fails in vim_regcomp()
—
Reply to this email directly, view it on GitHub.
You are receiving this because you are subscribed to this thread.![]()
@chrisbra wrote:
This patch avoids the segfault. Not sure if this is correct:
The patch uses siemsg(…). If it is possible to reach this path, then it should not be an internal error.
Internal errors should never happen, unless there is a bug.
siemsg(…) will dump core when building with -DABORT_ON_INTERNAL_ERROR on purpose to be able to detect bugs.
—
Reply to this email directly, view it on GitHub, or unsubscribe.
You are receiving this because you are subscribed to this thread.![]()
The idea was to give an internal error message letting the user know that there is a problem with the provided pattern. I thought we had some internal_error_message function. Perhaps using internal_error_no_abort() then?
Also my intention was, to let the user know he should report this pattern as an error to us. I forgot to spell it out however.
—
Reply to this email directly, view it on GitHub.
You are receiving this because you are subscribed to this thread.![]()
Thanks for digging up the info. It's better to not cause "regprog" to become NULL.
We can keep it around and only free it when compiling the pattern works.
That one engine manages to compile the pattern and the other doesn't is not always a real bug. The behavior may differ for corner cases, thus using an internal error does not seem appropriate.
—
Reply to this email directly, view it on GitHub.
You are receiving this because you are subscribed to this thread.![]()
—
Reply to this email directly, view it on GitHub.
You are receiving this because you are subscribed to this thread.![]()