Frew Schmidt <fri...@gmail.com> wrote:

> On Wednesday, May 11, 2016 at 2:18:31 AM UTC-7, Dominique Pelle wrote:
>> [ ... ]
>> Thanks. I should add: asan writes errors (if any) on stderr by default,
>> and since vim puts the terminal in cooked mode, asan error can be
>> garbled.  So it's best to redirect stderr.  The ASAN_OPTIONS
>> environment variable can be used for this. I put this in my ~/.bashrc:
>>
>> export 
>> ASAN_OPTIONS="check_initialization_order=1:strict_init_order=1:detect_stack_use_after_return=1:detect_leaks=0:log_path=/home/pel/asan.log:abort_on_error=1"
>>
>> The relevant part to redirect errors is  "log_path=/home/pel/asan.log"
>> (obviously you can put a different file name)
>>
>> See https://github.com/google/sanitizers/wiki/AddressSanitizerFlags
>> for more details.
>>
>> > FWIW though, I suspect that a skilled practitioner might be able
>> > to suss out the actual cause of the bug with the coredump I already have.
>>
>> It may not be so easy with a gdb stack alone: the memory error may
>> have happened much earlier than where the crash is detected in gdb.
>> That's why asan helps: if freed memory is accessed for example, the
>> error will be reported immediately when accessed, and asan will give
>> more information:
>> - the stack where freed memory is accessed
>> - the stack where memory was previously freed
>> - the stack where memory was previously allocated
>>
>> Regards
>> Dominique
>
> Ok, sounds good.  I've set the logging to $HOME/asan-$$.pid. Will report back 
> when I have results.


Hi Frew

I downloaded your dotfiles from github and used them.
I noticed dotfiles for awesome so I suspected that you used
awesome and so I used it too.  Awesome window manager
also happened to be used in the other crash reported a
few days ago.  Awesome causes more resizes than non
tiling window manager, which I think is the key to reproduce
the bug.

I managed to reproduce a crash with a asan build of
vim-7.4.1829 using your dotfile. I'm not sure that my
crash is related to your crash, but it's crash anyway.
Asan reports:

=================================================================
==3602==ERROR: AddressSanitizer: stack-use-after-return on address
0x7f31e405da48 at pc 0x000000f9676f bp 0x7ffca9f03c70 sp
0x7ffca9f03c68
READ of size 8 at 0x7f31e405da48 thread T0
    #0 0xf9676e in nfa_regtry /home/pel/sb/vim/src/./regexp_nfa.c:6982
    #1 0xf93115 in nfa_regexec_both /home/pel/sb/vim/src/./regexp_nfa.c:7156
    #2 0xf91b4b in nfa_regexec_multi /home/pel/sb/vim/src/./regexp_nfa.c:7366
    #3 0xf8f195 in vim_regexec_multi /home/pel/sb/vim/src/regexp.c:8177
    #4 0x111f33c in next_search_hl /home/pel/sb/vim/src/screen.c:7700
    #5 0x10b105d in win_line /home/pel/sb/vim/src/screen.c:3527
    #6 0x10a3d0c in update_single_line /home/pel/sb/vim/src/screen.c:824
    #7 0x1771f96 in main_loop /home/pel/sb/vim/src/main.c:1306
    #8 0x175fc65 in main /home/pel/sb/vim/src/main.c:1051
    #9 0x7f31eba0bf44 in __libc_start_main
/build/eglibc-IRFzFh/eglibc-2.19/csu/libc-start.c:287
    #10 0x4ecf1c in _start ??:?

Address 0x7f31e405da48 is located in stack of thread T0 at offset 584 in frame
    #0 0x12eb47f in syn_current_attr /home/pel/sb/vim/src/syntax.c:1885

  This frame has 36 object(s):
    [32, 36) ''
    [48, 52) ''
    [64, 68) ''
    [80, 88) ''
    [112, 116) ''
    [128, 132) 'syn_id'
    [144, 160) 'endpos'
    [176, 192) 'hl_startpos'
    [208, 224) 'hl_endpos'
    [240, 256) 'eos_pos'
    [272, 288) 'eoe_pos'
    [304, 308) 'end_idx'
    [320, 324) 'idx'
    [336, 344) 'spp'
    [368, 376) 'cur_si'
    [400, 408) 'sip'
    [432, 436) 'startcol'
    [448, 452) 'endcol'
    [464, 472) 'flags'
    [496, 500) 'cchar'
    [512, 520) 'next_list'
    [544, 548) 'found_match'
    [560, 564) 'do_keywords'
    [576, 912) 'regmatch' <== Memory access at offset 584 is inside
this variable
    [976, 992) 'pos'
    [1008, 1012) 'lc_col'
    [1024, 1032) 'cur_extmatch'
    [1056, 1088) 'buf_chartab'
    [1120, 1128) 'line'
    [1152, 1156) 'keep_next_list'
    [1168, 1172) 'zero_width_next_list'
    [1184, 1208) 'zero_width_next_ga'
    [1248, 1252) 'r'
    [1264, 1280) 'startpos'
    [1296, 1304) 'lspp'
    [1328, 1344) 'sps'
HINT: this may be a false positive if your program uses some custom
stack unwind mechanism or swapcontext
      (longjmp and C++ exceptions *are* supported)
SUMMARY: AddressSanitizer: stack-use-after-return ??:0 ??
Shadow bytes around the buggy address:
  0x0fe6bc803af0: f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5
  0x0fe6bc803b00: f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5
  0x0fe6bc803b10: f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5
  0x0fe6bc803b20: f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5
  0x0fe6bc803b30: f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5
=>0x0fe6bc803b40: f5 f5 f5 f5 f5 f5 f5 f5 f5[f5]f5 f5 f5 f5 f5 f5
  0x0fe6bc803b50: f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5
  0x0fe6bc803b60: f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5
  0x0fe6bc803b70: f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5
  0x0fe6bc803b80: f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5
  0x0fe6bc803b90: f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5
Shadow byte legend (one shadow byte represents 8 application bytes):
  Addressable:           00
  Partially addressable: 01 02 03 04 05 06 07
  Heap left redzone:       fa
  Heap right redzone:      fb
  Freed heap region:       fd
  Stack left redzone:      f1
  Stack mid redzone:       f2
  Stack right redzone:     f3
  Stack partial redzone:   f4
  Stack after return:      f5
  Stack use after scope:   f8
  Global redzone:          f9
  Global init order:       f6
  Poisoned by user:        f7
  Container overflow:      fc
  ASan internal:           fe
==3602==ABORTING

Code at regexp_nfa.c:6982 were error is detected:

6982  if (reg_startpos[0].lnum < 0)

reg_startpos is a global variable (pointer).
This pointer was set to a local variable somehow
in a function which already returned, so it's pointing
to invalid memory as a result of stack unwinding.

That local variable according to asan is regmatch
in stack frame of syn_current_attr(...) at syntax.c:1885.
Asan says:

Address 0x7f31e405da48 is located in stack of thread T0 at offset 584 in frame
    #0 0x12eb47f in syn_current_attr /home/pel/sb/vim/src/syntax.c:1885
...
  [576, 912) 'regmatch' <== Memory access at offset 584 is inside this variable

So the invalid memory access is at offset 584 - 576 = 8 in
regmatch.  regmatch is declared in syntax.c:1904 as:

1904     regmmatch_T regmatch;

With regmatch_T type being:

144 typedef struct
145 {
146     regprog_T           *regprog;
147     lpos_T              startpos[NSUBEXP];
148     lpos_T              endpos[NSUBEXP];
149     int                 rmm_ic;
150     colnr_T             rmm_maxcol;     /* when not zero: maximum column */
151 } regmmatch_T;

Offset 8 in that struct is the beginning of field startpos
(since I used x86_64, so sizeof(regprog) == 8)
which is consistent with were error is reported in
regexp_nfa.c:6982:

6982  if (reg_startpos[0].lnum < 0)

I think I see where the bug comes from: local variable
regmatch at syntax.c:1904 is passed by address
as 1st argument of syn_regexp(...) in syntax.c:

2116                             r = syn_regexec(&regmatch,
2117                                              current_lnum,
2118                                              (colnr_T)lc_col,
2119                                              IF_SYN_TIME(&spp->sp_time));

syn_regexec(...) is:

   3291     static int
   3292 syn_regexec(
   3293     regmmatch_T *rmp,
   3294     linenr_T    lnum,
   3295     colnr_T     col,
   3296     syn_time_T  *st UNUSED)
   3297 {
   3298     int r;
   3299 #ifdef FEAT_PROFILE
   3300     proftime_T  pt;
   3301
   3302     if (syn_time_on)
   3303         profile_start(&pt);
   3304 #endif
   3305
   3306     rmp->rmm_maxcol = syn_buf->b_p_smc;
!!!3307     r = vim_regexec_multi(rmp, syn_win, syn_buf, lnum, col, NULL);

rmp is then passed as 1st argument of vim_regexec_multi(...)
in regexp.c:3307

   8168     long
   8169 vim_regexec_multi(
   8170     regmmatch_T *rmp,
   8171     win_T       *win,           /* window in which to search or NULL */
   8172     buf_T       *buf,           /* buffer in which to search */
   8173     linenr_T    lnum,           /* nr of line to start looking
for match */
   8174     colnr_T     col,            /* column to start looking for match */
   8175     proftime_T  *tm)            /* timeout limit or NULL */
   8176 {
!!!8177     int result = rmp->regprog->engine->regexec_multi(
   8178                                                 rmp, win, buf,
lnum, col, tm);

rmp is then passed to rmp->regprog->engine->regexec_multi(rmp, ...)
which is a function pointer, which I think points to nfa_regexec_multi(...):

   7344     static long
   7345 nfa_regexec_multi(
   7346     regmmatch_T *rmp,
   7347     win_T       *win,           /* window in which to search or NULL */
   7348     buf_T       *buf,           /* buffer in which to search */
   7349     linenr_T    lnum,           /* nr of line to start looking
for match */
   7350     colnr_T     col,            /* column to start looking for match */
   7351     proftime_T  *tm)            /* timeout limit or NULL */
   7352 {
   7353     reg_match = NULL;
!!! 7354     reg_mmatch = rmp;

At line regexp_nfa.c:7354, rmp pointer is copied in
global variable reg_mmatch.  That's dangerous since
rmp pointed to a variable in the stack in regmatch
at syntax.c:1904. So when regmatch(...) function
returns, there is a danger that  global variable
reg_mmatch still points to an unwinded stack frame,
and if it used, vim will use invalid memory causing
the asan error reported above.

Now I'm not sure how to fix it, but hopefully someone
can.

This kind of error is detected by asan but cannot be
detected by valgrind.

This is how I reproduced the crash.  I opened to
instances of gvim from 2 terminals in Awesome WM:

$ vim -f -g
$ vim -f -g

In each of them, I opened a help file  (:help).
I chose a help file because they contain concealed
chars.  I then entered tiled mode in awesome WM
(Mod + Space), where Mod is Windows key.
I then pressed Mod-h and Mod-l multiple times to resize
multiple windows.  After a while, the crash happened.
This is the same scenario reported a few days
ago.

Regards
Dominique

-- 
-- 
You received this message from the "vim_use" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php

--- 
You received this message because you are subscribed to the Google Groups 
"vim_use" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to vim_use+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to