Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve ASAN CI testing #1425

Closed
wants to merge 3 commits into from
Closed

Conversation

jamessan
Copy link
Contributor

  • Enable -DEXITFREE on the CI builds which perform ASAN testing
  • Configure ASAN to print the stack traces and write the logs out to files
  • Fail the CI build if non-empty ASAN logs are found, and display the contents in the CI logs

.travis.yml Outdated
@@ -19,8 +19,8 @@ env:
- BUILD=yes TEST=test COVERAGE=no FEATURES=huge SHADOWOPT= SRCDIR=./src CHECK_AUTOCONF=no
"CONFOPT='--enable-perlinterp --enable-pythoninterp --enable-rubyinterp --enable-luainterp'"
# ASAN build
- BUILD=yes TEST=test SANITIZER_CFLAGS="-g -O1 -fsanitize=address -fno-omit-frame-pointer" FEATURES=huge SRCDIR=./src CHECK_AUTOCONF=no
"CONFOPT='--enable-perlinterp --enable-pythoninterp --enable-rubyinterp --enable-luainterp'"
- BUILD=yes TEST=test SANITIZER_CFLAGS="-g -O1 -DEXITFREE -fsanitize=address -fno-omit-frame-pointer" FEATURES=huge SRCDIR=./src CHECK_AUTOCONF=no
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could also consider compiling with -DABORT_ON_INTERNAL_ERROR in CI to make internal errors more obvious.

Copy link
Contributor Author

@jamessan jamessan Jan 29, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good suggestion. Added.

@jamessan
Copy link
Contributor Author

This is going to fail due to a buffer overrun introduced in v8.0.0250

=================================================================
==6350==ERROR: AddressSanitizer: global-buffer-overflow on address 0x0000009def16 at pc 0x6c0609 bp 0x7ffd441c3330 sp 0x7ffd441c3328
READ of size 1 at 0x0000009def16 thread T0
    #0 0x6c0608 in utf_head_off /home/travis/build/jamessan/vim/src/mbyte.c:3746
    #1 0x961017 in getvcol /home/travis/build/jamessan/vim/src/charset.c:1303
    #2 0x9621b1 in getvvcol /home/travis/build/jamessan/vim/src/charset.c:1477
    #3 0x6b49ad in curs_columns /home/travis/build/jamessan/vim/src/move.c:964
    #4 0x8d2769 in scroll_to_fraction /home/travis/build/jamessan/vim/src/window.c:5827
    #5 0x8c79e6 in frame_new_height /home/travis/build/jamessan/vim/src/window.c:2862
    #6 0x8cc8df in winframe_remove /home/travis/build/jamessan/vim/src/window.c:2673
    #7 0x8cbcf3 in win_free_mem /home/travis/build/jamessan/vim/src/window.c:2571
    #8 0x8c0a4c in win_close /home/travis/build/jamessan/vim/src/window.c:2420
    #9 0x8cd85e in close_others /home/travis/build/jamessan/vim/src/window.c:3372
    #10 0x5a2a56 in do_one_cmd /home/travis/build/jamessan/vim/src/ex_docmd.c:2981
    #11 0x59814a in do_cmdline /home/travis/build/jamessan/vim/src/ex_docmd.c:1120
    #12 0x6a1cfc in free_all_mem /home/travis/build/jamessan/vim/src/misc2.c:1079
    #13 0x74f373 in mch_exit /home/travis/build/jamessan/vim/src/os_unix.c:3345
    #14 0x96c6f0 in getout /home/travis/build/jamessan/vim/src/main.c:1495
    #15 0x5b7838 in ex_quit_all /home/travis/build/jamessan/vim/src/ex_docmd.c:7367
    #16 0x5a2a56 in do_one_cmd /home/travis/build/jamessan/vim/src/ex_docmd.c:2981
    #17 0x59814a in do_cmdline /home/travis/build/jamessan/vim/src/ex_docmd.c:1120
    #18 0x6e917f in nv_colon /home/travis/build/jamessan/vim/src/normal.c:5401
    #19 0x6ce220 in normal_cmd /home/travis/build/jamessan/vim/src/normal.c:1150
    #20 0x96d292 in main_loop /home/travis/build/jamessan/vim/src/main.c:1311
    #21 0x96b3c6 in vim_main2 /home/travis/build/jamessan/vim/src/main.c:877
    #22 0x968475 in main /home/travis/build/jamessan/vim/src/main.c:415
    #23 0x2ae28e9e27ec (/lib/x86_64-linux-gnu/libc.so.6+0x217ec)
    #24 0x4bac9c in _start (/home/travis/build/jamessan/vim/src/vim+0x4bac9c)

0x0000009def16 is located 42 bytes to the left of global variable '.str9' from 'memline.c' (0x9def40) of size 3
  '.str9' is ascii string '.s'
0x0000009def16 is located 21 bytes to the right of global variable '.str8' from 'memline.c' (0x9def00) of size 1
  '.str8' is ascii string ''
SUMMARY: AddressSanitizer: global-buffer-overflow /home/travis/build/jamessan/vim/src/mbyte.c:3746 utf_head_off

@brammool
Copy link
Contributor

brammool commented Jan 29, 2017 via email

@dpelle
Copy link
Member

dpelle commented Jan 29, 2017

Configure ASAN to print the stack traces and write the logs out to files

This is not needed. A simpler solution to detect the asan failure in CI is to remove
the dash in src/testdir/Makefile as follows:

diff --git a/src/testdir/Makefile b/src/testdir/Makefile
index 08f11cd..bb0249a 100644
--- a/src/testdir/Makefile
+++ b/src/testdir/Makefile
@@ -78,7 +78,7 @@ test1.out: test1.in
        # 200 msec is sufficient, but only modern sleep supports a fraction of
        # a second, fall back to a second if it fails.
        @-/bin/sh -c "sleep .2 > /dev/null 2>&1 || sleep 1"
-       -$(RUN_VIM) $*.in
+       $(RUN_VIM) $*.in
 
        # For flaky tests retry one time.  No tests at the moment.
        #@/bin/sh -c "if test -f test.out -a $* = test61; then \
@@ -108,7 +108,7 @@ bench_re_freeze.out: bench_re_freeze.vim
        # 200 msec is sufficient, but only modern sleep supports a fraction of
        # a second, fall back to a second if it fails.
        @-/bin/sh -c "sleep .2 > /dev/null 2>&1 || sleep 1"
-       -$(RUN_VIM) $*.in
+       $(RUN_VIM) $*.in
        @/bin/sh -c "if test -f benchmark.out; then cat benchmark.out; fi"
 
 nolog:

It also has other advantages:

  • If asan fails, it prints the error immediately so we know which test fails
  • it also makes CI fail if a regular (non-asan) build was to crash when
    vim exits (as a result of bug with -DEXITFREE or other reasons).

Without this change (removal of dash), all tests can succeed despite
vim crashing on exit, which is bad.

I'm going to create a PR with the dash removal to check that works as intended
on all plaforms.

@brammool
Copy link
Contributor

brammool commented Jan 29, 2017 via email

@dpelle
Copy link
Member

dpelle commented Jan 29, 2017

[...] A simpler solution to detect the asan failure in CI is to remove
the dash in src/testdir/Makefile as follows:
...
Doesn't this mean the first test that fails causes an abort, no further
tests are executed? That's bad, if several tests fail we need to know.

If a test fails, VIMRUN still return 0 normally. So all tests will run.
I just tried it, by faking several tests to fails, and verifying that all failing
tests were reported (not just the first one).

But if VIMRUN returns something else than 0 (as a result of of a crash for
example), then yes, no further tests will run in that case. I think that if vim
crashes, it's severe and running all tests is not really needed.
But it's debatable.

In any cases, it's better than currently saying "all tests passed" despite the
fact that vim may have crashed. We need to do something about that one
way or another.

@brammool brammool closed this in 432c839 Jan 30, 2017
@jamessan
Copy link
Contributor Author

I think you meant to close #1427 with 8.0.0272, not this PR.

@brammool brammool reopened this Jan 30, 2017
@brammool
Copy link
Contributor

Sorry, Dominique's comment was in this thread.

@jamessan
Copy link
Contributor Author

jamessan commented Feb 3, 2017

Rebased to include Dominique's changes and that shows the ASAN failure is happening when running test7.in. The suggested change to check pos->col > 0 didn't have any effect.

@dpelle
Copy link
Member

dpelle commented Feb 4, 2017

I see the same global-buffer-overflow reported by @jamessan, when building
vim-8.0.303 with -DEXITFREE and asan. My asan output is a bit better than
the one posted earlier, as I see line number for globals:

 0x000000d21d36 is located 42 bytes to the left of global variable '<string literal>' defined in 'memline.c:1153:6' (0xd21d60) of size 3
  '<string literal>' is ascii string '.s'
0x000000d21d36 is located 21 bytes to the right of global variable '<string literal>' defined in 'memline.c:1147:20' (0xd21d20) of size 1
  '<string literal>' is ascii string ''

Code in memline.c:

  1141     /*
  1142      * If the file name ends in ".s[uvw][a-z]" we assume this is the swap file.
  1143      * Otherwise a search is done to find the swap file(s).
  1144      */
  1145     fname = curbuf->b_fname;
  1146     if (fname == NULL)              /* When there is no file name */
!!1147         fname = (char_u *)"";
  1148     len = (int)STRLEN(fname);
  1149     if (len >= 4 &&
  1150 #if defined(VMS)
  1151             STRNICMP(fname + len - 4, "_s" , 2)
  1152 #else
!!1153             STRNICMP(fname + len - 4, ".s" , 2)
1154 #endif

I don't understand yet what's causing the overflow.

valgrind won't detect this kind of bugs, as only asan detects overflows
in global variables as described in this comparison page:

https://github.com/google/sanitizers/wiki/AddressSanitizerComparisonOfMemoryTools

Full error reported by asan in test7, with vim-8.0.303:

VIMRUNTIME=../../runtime; export VIMRUNTIME;  ../vim -f  -u unix.vim -U NONE --noplugin --not-a-term -s dotest.in test7.in
=================================================================
==5875==ERROR: AddressSanitizer: global-buffer-overflow on address 0x000000d21d36 at pc 0x000000890a51 bp 0x7ffe71d46860 sp 0x7ffe71d46858
READ of size 1 at 0x000000d21d36 thread T0
    #0 0x890a50 in utf_head_off /home/pel/sb/vim/src/mbyte.c:3746
    #1 0xc7818a in getvcol /home/pel/sb/vim/src/charset.c:1303
    #2 0xc7a082 in getvvcol /home/pel/sb/vim/src/charset.c:1477
    #3 0x87a65a in curs_columns /home/pel/sb/vim/src/move.c:964
    #4 0xc33915 in scroll_to_fraction /home/pel/sb/vim/src/window.c:5827
    #5 0xc1e20b in win_new_height /home/pel/sb/vim/src/window.c:5711
    #6 0xc1f625 in frame_new_height /home/pel/sb/vim/src/window.c:2862
    #7 0xc2842d in winframe_remove /home/pel/sb/vim/src/window.c:2673
    #8 0xc270c8 in win_free_mem /home/pel/sb/vim/src/window.c:2571
    #9 0xc12aaf in win_close /home/pel/sb/vim/src/window.c:2420
    #10 0xc2a6a7 in close_others /home/pel/sb/vim/src/window.c:3372 (discriminator 2)
    #11 0x6d9d51 in ex_only /home/pel/sb/vim/src/ex_docmd.c:7741
    #12 0x6a82aa in do_one_cmd /home/pel/sb/vim/src/ex_docmd.c:2981
    #13 0x697100 in do_cmdline /home/pel/sb/vim/src/ex_docmd.c:1120
    #14 0x69a865 in do_cmdline_cmd /home/pel/sb/vim/src/ex_docmd.c:720
    #15 0x859a71 in free_all_mem /home/pel/sb/vim/src/misc2.c:1079
    #16 0x97b1ed in mch_exit /home/pel/sb/vim/src/os_unix.c:3345
    #17 0xc8ed7d in getout /home/pel/sb/vim/src/main.c:1499
    #18 0x6db49d in ex_quit_all /home/pel/sb/vim/src/ex_docmd.c:7374
    #19 0x6a82aa in do_one_cmd /home/pel/sb/vim/src/ex_docmd.c:2981
    #20 0x697100 in do_cmdline /home/pel/sb/vim/src/ex_docmd.c:1120
    #21 0x8cdf6b in nv_colon /home/pel/sb/vim/src/normal.c:5403
    #22 0x8a472f in normal_cmd /home/pel/sb/vim/src/normal.c:1150
    #23 0xc8feeb in main_loop /home/pel/sb/vim/src/main.c:1315
    #24 0xc8c6eb in vim_main2 /home/pel/sb/vim/src/main.c:877
    #25 0xc85a37 in main /home/pel/sb/vim/src/main.c:415
    #26 0x2b082e05bf44 in __libc_start_main /build/eglibc-oGUzwX/eglibc-2.19/csu/libc-start.c:287
    #27 0x41e5cb in _start ??:?

0x000000d21d36 is located 42 bytes to the left of global variable '<string literal>' defined in 'memline.c:1153:6' (0xd21d60) of size 3
  '<string literal>' is ascii string '.s'
0x000000d21d36 is located 21 bytes to the right of global variable '<string literal>' defined in 'memline.c:1147:20' (0xd21d20) of size 1
  '<string literal>' is ascii string ''
SUMMARY: AddressSanitizer: global-buffer-overflow (/home/pel/sb/vim/src/vim+0x890a50)
Shadow bytes around the buggy address:
  0x00008019c350: 00 00 00 00 00 00 00 05 f9 f9 f9 f9 05 f9 f9 f9
  0x00008019c360: f9 f9 f9 f9 00 00 00 05 f9 f9 f9 f9 00 00 00 05
  0x00008019c370: f9 f9 f9 f9 00 00 00 00 00 03 f9 f9 f9 f9 f9 f9
  0x00008019c380: 00 00 00 00 02 f9 f9 f9 f9 f9 f9 f9 00 00 00 00
  0x00008019c390: 01 f9 f9 f9 f9 f9 f9 f9 00 00 00 00 00 00 00 05
=>0x00008019c3a0: f9 f9 f9 f9 01 f9[f9]f9 f9 f9 f9 f9 03 f9 f9 f9
  0x00008019c3b0: f9 f9 f9 f9 07 f9 f9 f9 f9 f9 f9 f9 00 00 00 00
  0x00008019c3c0: f9 f9 f9 f9 00 00 00 00 00 07 f9 f9 f9 f9 f9 f9
  0x00008019c3d0: 00 00 05 f9 f9 f9 f9 f9 00 00 00 05 f9 f9 f9 f9
  0x00008019c3e0: 00 00 00 00 00 00 00 00 01 f9 f9 f9 f9 f9 f9 f9
  0x00008019c3f0: 00 f9 f9 f9 f9 f9 f9 f9 00 00 00 00 00 03 f9 f9
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
  Freed heap region:       fd
  Stack left redzone:      f1
  Stack mid redzone:       f2
  Stack right redzone:     f3
  Stack after return:      f5
  Stack use after scope:   f8
  Global redzone:          f9
  Global init order:       f6
  Poisoned by user:        f7
  Container overflow:      fc
  Array cookie:            ac
  Intra object redzone:    bb
  ASan internal:           fe
  Left alloca redzone:     ca
  Right alloca redzone:    cb
==5875==ABORTING
Vim: Caught deadly signal ABRT
ASAN:DEADLYSIGNAL
=================================================================

I also see that overflow in 2 other tests:

  • test test_changelist.in
  • test_listlbr_utf8.in
VIMRUNTIME=../../runtime; export VIMRUNTIME;  ../vim -f  -u unix.vim -U NONE --noplugin --not-a-term -s dotest.in test_changelist.in
=================================================================
==7833==ERROR: AddressSanitizer: global-buffer-overflow on address 0x000000d21d23 at pc 0x000000890a51 bp 0x7fffaf2cebe0 sp 0x7fffaf2cebd8
READ of size 1 at 0x000000d21d23 thread T0
    #0 0x890a50 in utf_head_off /home/pel/sb/vim/src/mbyte.c:3746
VIMRUNTIME=../../runtime; export VIMRUNTIME;  ../vim -f  -u unix.vim -U NONE --noplugin --not-a-term -s dotest.in test_changelist.in
=================================================================
==7833==ERROR: AddressSanitizer: global-buffer-overflow on address 0x000000d21d23 at pc 0x000000890a51 bp 0x7fffaf2cebe0 sp 0x7fffaf2cebd8
READ of size 1 at 0x000000d21d23 thread T0
    #0 0x890a50 in utf_head_off /home/pel/sb/vim/src/mbyte.c:3746
    #1 0xc7818a in getvcol /home/pel/sb/vim/src/charset.c:1303
    #2 0xc7a082 in getvvcol /home/pel/sb/vim/src/charset.c:1477
    #3 0x87a65a in curs_columns /home/pel/sb/vim/src/move.c:964
    #4 0xc1e453 in win_new_width /home/pel/sb/vim/src/window.c:5854
    #5 0xc1eb76 in frame_new_width /home/pel/sb/vim/src/window.c:3071
    #6 0xc28ae0 in winframe_remove /home/pel/sb/vim/src/window.c:2710
    #7 0xc270c8 in win_free_mem /home/pel/sb/vim/src/window.c:2571
    #8 0xc12aaf in win_close /home/pel/sb/vim/src/window.c:2420
    #9 0xc2a6a7 in close_others /home/pel/sb/vim/src/window.c:3372 (discriminator 2)
    #10 0x6d9d51 in ex_only /home/pel/sb/vim/src/ex_docmd.c:7741
    #11 0x6a82aa in do_one_cmd /home/pel/sb/vim/src/ex_docmd.c:2981
    #12 0x697100 in do_cmdline /home/pel/sb/vim/src/ex_docmd.c:1120
    #13 0x69a865 in do_cmdline_cmd /home/pel/sb/vim/src/ex_docmd.c:720
    #14 0x859a71 in free_all_mem /home/pel/sb/vim/src/misc2.c:1079
    #15 0x97b1ed in mch_exit /home/pel/sb/vim/src/os_unix.c:3345
    #16 0xc8ed7d in getout /home/pel/sb/vim/src/main.c:1499
    #17 0x6db49d in ex_quit_all /home/pel/sb/vim/src/ex_docmd.c:7374
    #18 0x6a82aa in do_one_cmd /home/pel/sb/vim/src/ex_docmd.c:2981
    #19 0x697100 in do_cmdline /home/pel/sb/vim/src/ex_docmd.c:1120
    #20 0x8cdf6b in nv_colon /home/pel/sb/vim/src/normal.c:5403
    #21 0x8a472f in normal_cmd /home/pel/sb/vim/src/normal.c:1150
    #22 0xc8feeb in main_loop /home/pel/sb/vim/src/main.c:1315
    #23 0xc8c6eb in vim_main2 /home/pel/sb/vim/src/main.c:877
    #24 0xc85a37 in main /home/pel/sb/vim/src/main.c:415
    #25 0x2b85b3adbf44 in __libc_start_main /build/eglibc-oGUzwX/eglibc-2.19/csu/libc-start.c:287
    #26 0x41e5cb in _start ??:?

0x000000d21d23 is located 61 bytes to the left of global variable '<string literal>' defined in 'memline.c:1153:6' (0xd21d60) of size 3
  '<string literal>' is ascii string '.s'
0x000000d21d23 is located 2 bytes to the right of global variable '<string literal>' defined in 'memline.c:1147:20' (0xd21d20) of size 1
  '<string literal>' is ascii string ''
SUMMARY: AddressSanitizer: global-buffer-overflow (/home/pel/sb/vim/src/vim+0x890a50)
Shadow bytes around the buggy address:
  0x00008019c350: 00 00 00 00 00 00 00 05 f9 f9 f9 f9 05 f9 f9 f9
  0x00008019c360: f9 f9 f9 f9 00 00 00 05 f9 f9 f9 f9 00 00 00 05
  0x00008019c370: f9 f9 f9 f9 00 00 00 00 00 03 f9 f9 f9 f9 f9 f9
  0x00008019c380: 00 00 00 00 02 f9 f9 f9 f9 f9 f9 f9 00 00 00 00
  0x00008019c390: 01 f9 f9 f9 f9 f9 f9 f9 00 00 00 00 00 00 00 05
=>0x00008019c3a0: f9 f9 f9 f9[01]f9 f9 f9 f9 f9 f9 f9 03 f9 f9 f9
  0x00008019c3b0: f9 f9 f9 f9 07 f9 f9 f9 f9 f9 f9 f9 00 00 00 00
  0x00008019c3c0: f9 f9 f9 f9 00 00 00 00 00 07 f9 f9 f9 f9 f9 f9
  0x00008019c3d0: 00 00 05 f9 f9 f9 f9 f9 00 00 00 05 f9 f9 f9 f9
  0x00008019c3e0: 00 00 00 00 00 00 00 00 01 f9 f9 f9 f9 f9 f9 f9
  0x00008019c3f0: 00 f9 f9 f9 f9 f9 f9 f9 00 00 00 00 00 03 f9 f9
VIMRUNTIME=../../runtime; export VIMRUNTIME;  ../vim -f  -u unix.vim -U NONE --noplugin --not-a-term -s dotest.in test_listlbr_utf8.in
=================================================================
==9329==ERROR: AddressSanitizer: global-buffer-overflow on address 0x000000d21d24 at pc 0x000000890a51 bp 0x7ffc43e0dca0 sp 0x7ffc43e0dc98
READ of size 1 at 0x000000d21d24 thread T0
    #0 0x890a50 in utf_head_off /home/pel/sb/vim/src/mbyte.c:3746
    #1 0xc7818a in getvcol /home/pel/sb/vim/src/charset.c:1303
    #2 0xc7a082 in getvvcol /home/pel/sb/vim/src/charset.c:1477
    #3 0x87a65a in curs_columns /home/pel/sb/vim/src/move.c:964
    #4 0xc1e453 in win_new_width /home/pel/sb/vim/src/window.c:5854
    #5 0xc1eb76 in frame_new_width /home/pel/sb/vim/src/window.c:3071
    #6 0xc28ae0 in winframe_remove /home/pel/sb/vim/src/window.c:2710
    #7 0xc270c8 in win_free_mem /home/pel/sb/vim/src/window.c:2571
    #8 0xc12aaf in win_close /home/pel/sb/vim/src/window.c:2420
    #9 0xc2a6a7 in close_others /home/pel/sb/vim/src/window.c:3372 (discriminator 2)
    #10 0x6d9d51 in ex_only /home/pel/sb/vim/src/ex_docmd.c:7741
    #11 0x6a82aa in do_one_cmd /home/pel/sb/vim/src/ex_docmd.c:2981
    #12 0x697100 in do_cmdline /home/pel/sb/vim/src/ex_docmd.c:1120
    #13 0x69a865 in do_cmdline_cmd /home/pel/sb/vim/src/ex_docmd.c:720
    #14 0x859a71 in free_all_mem /home/pel/sb/vim/src/misc2.c:1079
    #15 0x97b1ed in mch_exit /home/pel/sb/vim/src/os_unix.c:3345
    #16 0xc8ed7d in getout /home/pel/sb/vim/src/main.c:1499
    #17 0x6db49d in ex_quit_all /home/pel/sb/vim/src/ex_docmd.c:7374
    #18 0x6a82aa in do_one_cmd /home/pel/sb/vim/src/ex_docmd.c:2981
    #19 0x697100 in do_cmdline /home/pel/sb/vim/src/ex_docmd.c:1120
    #20 0x8cdf6b in nv_colon /home/pel/sb/vim/src/normal.c:5403
    #21 0x8a472f in normal_cmd /home/pel/sb/vim/src/normal.c:1150
    #22 0xc8feeb in main_loop /home/pel/sb/vim/src/main.c:1315
    #23 0xc8c6eb in vim_main2 /home/pel/sb/vim/src/main.c:877
    #24 0xc85a37 in main /home/pel/sb/vim/src/main.c:415
    #25 0x2b8db14b5f44 in __libc_start_main /build/eglibc-oGUzwX/eglibc-2.19/csu/libc-start.c:287
    #26 0x41e5cb in _start ??:?

0x000000d21d24 is located 60 bytes to the left of global variable '<string literal>' defined in 'memline.c:1153:6' (0xd21d60) of size 3
  '<string literal>' is ascii string '.s'
0x000000d21d24 is located 3 bytes to the right of global variable '<string literal>' defined in 'memline.c:1147:20' (0xd21d20) of size 1
  '<string literal>' is ascii string ''
SUMMARY: AddressSanitizer: global-buffer-overflow (/home/pel/sb/vim/src/vim+0x890a50)
Shadow bytes around the buggy address:
  0x00008019c350: 00 00 00 00 00 00 00 05 f9 f9 f9 f9 05 f9 f9 f9
  0x00008019c360: f9 f9 f9 f9 00 00 00 05 f9 f9 f9 f9 00 00 00 05
  0x00008019c370: f9 f9 f9 f9 00 00 00 00 00 03 f9 f9 f9 f9 f9 f9
  0x00008019c380: 00 00 00 00 02 f9 f9 f9 f9 f9 f9 f9 00 00 00 00
  0x00008019c390: 01 f9 f9 f9 f9 f9 f9 f9 00 00 00 00 00 00 00 05
=>0x00008019c3a0: f9 f9 f9 f9[01]f9 f9 f9 f9 f9 f9 f9 03 f9 f9 f9
  0x00008019c3b0: f9 f9 f9 f9 07 f9 f9 f9 f9 f9 f9 f9 00 00 00 00
  0x00008019c3c0: f9 f9 f9 f9 00 00 00 00 00 07 f9 f9 f9 f9 f9 f9
  0x00008019c3d0: 00 00 05 f9 f9 f9 f9 f9 00 00 00 05 f9 f9 f9 f9
  0x00008019c3e0: 00 00 00 00 00 00 00 00 01 f9 f9 f9 f9 f9 f9 f9
  0x00008019c3f0: 00 f9 f9 f9 f9 f9 f9 f9 00 00 00 00 00 03 f9 f9

@dpelle
Copy link
Member

dpelle commented Feb 4, 2017

Adding some printf, I sort of see what's going on with the asan error,
but I have no fix yet.

Function ml_get_buf() is called and returns an empty constant
string at line memline.c:2464:

  2435     char_u  *
  2436 ml_get_buf(
  ...
  2463     if (buf->b_ml.ml_mfp == NULL)       /* there are no lines */
!!2464         return (char_u *)"";

That ml_get_buf() calls came from getvcol() at charset.c:1294:

  1276     void
  1277 getvcol(
  ...
!!1294     line = ptr = ml_get_buf(wp->w_buffer, pos->lnum, FALSE);
  1295     if (pos->col == MAXCOL)
  1296         posptr = NULL;  /* continue until the NUL */
  1297     else
  1298     {
!!1299         posptr = ptr + pos->col;
  1300 #ifdef FEAT_MBYTE
  1301         if (has_mbyte)
  1302             /* always start on the first byte */
  1303             posptr -= (*mb_head_off)(line, posptr);
  1304 #endif

So 'line' pointer at charset.c:1294 points to a global
constant empty string "".

Then at charset.c:1999, we add pos->col, which happens to
be 22, so posptr is an invalid pointer 22 bytes to the right of
a global constant string "". We then call utf_head_off()
at charset.c:1303 with the invalid posptr, which will access an
invalid address.

The error from asan is thus correct, but a misleading because it
reported another empty string in memline.c:1147, which is completely
unrelated to the bug. The misleading error happens I suppose, because
the compiler or linker has merged identical constant strings.
Nevertheless, the bug in vim is real.

@brammool
Copy link
Contributor

brammool commented Feb 5, 2017 via email

@jamessan
Copy link
Contributor Author

jamessan commented Mar 5, 2017

Rebased on 8.0.0413. The ASAN failures that were detected before have been fixed, so this should be good to merge now.

@brammool brammool closed this in a382868 Mar 5, 2017
@jamessan jamessan deleted the use-EXITFREE-with-ASAN branch March 13, 2017 15:49
chrisbra pushed a commit to chrisbra/vim that referenced this pull request Mar 25, 2017
Problem:    Crash on exit is not detected when running tests.
Solution:   Remove the dash before the command. (Dominique Pelle, closes
            vim#1425)
chrisbra pushed a commit to chrisbra/vim that referenced this pull request Mar 25, 2017
Problem:    ASAN logs are disabled and don't cause a failure.
Solution:   Enable ASAN logs and fail if not empty. (James McCoy,
            closes vim#1425)
desvp pushed a commit to desvp/vim that referenced this pull request May 30, 2017
Problem:    Crash on exit is not detected when running tests.
Solution:   Remove the dash before the command. (Dominique Pelle, closes
            vim#1425)
desvp pushed a commit to desvp/vim that referenced this pull request May 30, 2017
Problem:    ASAN logs are disabled and don't cause a failure.
Solution:   Enable ASAN logs and fail if not empty. (James McCoy,
            closes vim#1425)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants