Bram Moolenaar <[email protected]> wrote:
> Christian Brabandt wrote:
>
>> > > On Mo, 13 Jun 2016, Christian Brabandt wrote:
>> > >
>> > > > Something between 7.4.1924 and 7.4.1926 broke the daily binary built:
>> > > >
>> > > > ..\gvim -u dos.vim -U NONE --noplugin --not-a-term "+set ff=dos|f
>> > > > dostmp\test58.in|wq" test58.in
>> > > > move test58.in test58.in.bak
>> > > > 1 file(s) moved.
>> > > > copy dostmp\test58.in test58.in
>> > > > 1 file(s) copied.
>> > > > copy test58.ok test.ok
>> > > > 1 file(s) copied.
>> > > > ..\gvim -u dos.vim -U NONE --noplugin --not-a-term -s dotest.in
>> > > > test58.in
>> > > > NMAKE : fatal error U1077: '..\gvim.EXE' : return code '0xc0000005'
>> > > > Stop.
>> > > >
>> > > > I rebuild that commit 3 times and it always breaks at that step for the
>> > > > 32bit build. Does anybody know, what that means?
>> > >
>> > > I think the crash happens in the quit command of the test58.in file
>> > > (function TestOne(), line 28)
>> > >
>> > > ,----
>> > > | " list all valid words
>> > > | spelldump
>> > > | %yank
>> > > | quit
>> > > | $put
>> > > `----
>> > >
>> > >
>> > > I stepped into it using a debugger, and I think the stacktrace shows,
>> > > that the crash happens in:
>> > > win_free(), when calling perl_win_free()
>> > > Stacktrace (sorry, only screenshot):
>> > > http://i.imgur.com/fzmHS9r.png
>> > >
>> > > Sorry, don't know how to further debug this.
>> > >
>> > > If someone wants knows how to debug it,
>> > > you can download a broken Gvim here:
>> > > https://github.com/chrisbra/vim-win32-installer/releases/tag/v7.4.1934_test
>> > > (only happens with the x86 versions).
>> >
>> > Hmm, since the test does not use Perl at all, w_perl_private should not
>> > have been set. If it's not NULL then perhaps it was corrupted?
>> > Perhaps if you step into perl_win_free() you can see what the value is?
>> >
>> > You could try commenting out the call to perl_win_free() and see if it
>> > finishes properly or then crashe somewhere else (e.g., when using other
>> > pointers next to w_perl_private, e.g. w_python_ref or w_mzscheme_ref).
>> >
>> > If you can set a watch point in this debugger, watching w_perl_private
>> > might also reveal something.
>>
>> It happens in mark.c:
>>
>> 174 /* If jumplist is full: remove oldest entry */
>> 175 if (++curwin->w_jumplistlen > JUMPLISTSIZE)
>> 176 {
>> 177 curwin->w_jumplistlen = JUMPLISTSIZE;
>> 178 vim_free(curwin->w_jumplist[0].fname);
>> 179 for (i = 1; i < JUMPLISTSIZE; ++i)
>> 180 curwin->w_jumplist[i - 1] = curwin->w_jumplist[i];
>> 181 }
>> 182 curwin->w_jumplistidx = curwin->w_jumplistlen;
>> 183 fm = &curwin->w_jumplist[curwin->w_jumplistlen - 1];
>> 184
>> 185 fm->fmark.mark = curwin->w_pcmark;
>> 186 fm->fmark.fnum = curbuf->b_fnum;
>> 187 fm->fname = NULL;
>> 188 # ifdef FEAT_VIMINFO
>> 189 fm->time_set = vim_time();
>> 190 # endif
>> 191 #endif
>>
>> somehow, w_jumplistlen isn't incremented, then fm access
>> curwin->w_jumplist[-1]
>> this goes on, until w_jumplistlen gets overwritten to a really high value
>> which
>> later causes curwin->w_perl_private to be set to 1.
>>
>> I don't understand why this happens, I tried adding some check statements,
>> so that
>> curwin->w_jumplistlen is always positive, but this didn't help for some
>> reason.
>>
>> Don't know how to further help here.
>
> Have you tried after patch 7.4.1939? It fixes a problem where
> w_jumplistlen was overwritten with a line number. Valgrind doesn't
> catch this because it's still within a struct.
Yes, I think that patch 7.4.1939 should fix this.
Below is a simplified version of the memory corruption, unfortunately
not detected by valgrind, asan (address sanitizer), ubsan (undefined
sanitizer) or compiler warnings:
$ cat corrupt.cpp
#include <stdio.h>
struct s_t {
int a[2];
int b;
};
int main()
{
s_t s;
s.a[0] = 0;
s.a[1] = 0;
s.b = 0;
int *p = &s.a[2]; // Taking end address of the array is OK.
p[0] = 1; // ... but this corrupts memory, typically writing into b.
// Print to make sure compiler does not optimize code out.
for (int i = 0; i < 2; ++i) {
printf("s.a[%d]=%d\n", i, s.a[i]);
}
printf("s.b=%d\n", s.b);
}
# Bug is not detected by asan...
$ g++ -Wall -fsanitize=address corrupt.cpp
$ ./a.out
s.a[0]=0
s.a[1]=0
s.b=1
# Bug is not detected by ubsan either...
$ g++ -Wall -fsanitize=undefined corrupt.cpp
$ ./a.out
s.a[0]=0
s.a[1]=0
s.b=1
# Bug is not detected by valgrind either...
$ g++ -Wall corrupt.cpp
$ valgrind ./a.out
==16570== Memcheck, a memory error detector
==16570== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==16570== Using Valgrind-3.10.1 and LibVEX; rerun with -h for copyright info
==16570== Command: ./a.out
==16570==
s.a[0]=0
s.a[1]=0
s.b=1
==16570==
==16570== HEAP SUMMARY:
==16570== in use at exit: 0 bytes in 0 blocks
==16570== total heap usage: 0 allocs, 0 frees, 0 bytes allocated
==16570==
==16570== All heap blocks were freed -- no leaks are possible
==16570==
==16570== For counts of detected and suppressed errors, rerun with: -v
==16570== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
It would be good if asan knew that p points into array s.a[..]
and so it's only allowed to access addresses between
&s.a[0] (included) .. s.a[2] (excluded) when dereferencing p.
I've asked the author of asan whether this is doable in asan.
Regards
Dominique
--
--
You received this message from the "vim_dev" 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_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
For more options, visit https://groups.google.com/d/optout.