On Feb 11, 2008 10:28 PM, Bram Moolenaar <[EMAIL PROTECTED]> wrote:
>
>
> Dominique Pelle wrote:
>
> > On Feb 5, 2008 8:40 AM, Tony Mechelynck <[EMAIL PROTECTED]> wrote:
> > >
> > > Kazuo Teramoto wrote:
> > > >> Same (start at X, stop at Y) for
> > > >> :call search("^", "e")
> > > >> :call search("^", "ce")
> > > >
> > > > Ouch, for me this is a little more serious, if I try this calls my vim
> > > > always segfault (I don't need a test file and using -u NONE -U none),
> > > > I don't know what need to be posted but the :version is
> > > >
> > > > VIM - Vi IMproved 7.0 (2006 May 7, compiled Aug 29 2007 10:59:43)
> > > > Included patches: 1-122, 234-235, 39
> > > > Big version without GUI. Features included (+) or not (-):
> > >
> > > ??? with patch 39 applied twice ??? none of 123-233 (a hundred and eleven
> > > missing patches) ??? and no "compiled-by" line ??? Oh, and it's a 7.0
> > > anyway.
> > > Maybe you ought to install a 7.1 version (of which the current patchlevel
> > > is
> > > 7.1.242)? See my "HowTo" page,
> > > http://users.skynet.be/antoine.mechelynck/vim/compunix.htm
> >
> >
> > I have a normal installation of vim-7.1.242 (all patches) and it's
> > crashing for me as well. I have the same version of vim on
> > 2 machines (one linux x66 and one linux x86_64) and it's only
> > crashing on the the x86_64 machine only.
> >
> > As soon as I type ":call search('\_s*a\_s*','e')" I get a core dump
> > on the x86_64 machine:
> >
> > $ ./vim
> > Vim: Caught deadly signal SEGV
> > Vim: preserving files...
> > Vim: Finished.
> > Segmentation fault (core dumped)
> >
> > $ gdb ./vim core
> > ...
> > Core was generated by `./vim'.
> > Program terminated with signal 11, Segmentation fault.
> > #0 0x00002b71866ebe47 in kill () from /lib64/libc.so.6
> > (gdb) bt
> > #0 0x00002b71866ebe47 in kill () from /lib64/libc.so.6
> > #1 0x000000000050e38d in may_core_dump () at os_unix.c:2950
> > #2 0x000000000050e328 in mch_exit (r=1) at os_unix.c:2915
> > #3 0x00000000004a5eb3 in getout (exitval=1) at main.c:1342
> > #4 0x00000000004d2128 in preserve_exit () at misc1.c:8355
> > #5 0x000000000050c73d in deathtrap (sigarg=11) at os_unix.c:1030
> > #6 <signal handler called>
> > #7 0x00000000004e0b33 in utf_head_off (base=0x9251c4 "c Y",
> > p=0x1009251c3 <Address 0x1009251c3 out of bounds>) at mbyte.c:2480
> > #8 0x0000000000539235 in searchit (win=0x831b90, buf=0x8333f0,
> > pos=0x7fff2690fa00, dir=1, pat=0x947c80 "\\_s*a\\_s*", count=1,
> > options=1088, pat_use=0, stop_lnum=0, tm=0x7fff2690f9e0) at search.c:848
> > #9 0x00000000004420e7 in search_cmn (argvars=0x7fff2690fbc0, match_pos=0x0,
> > flagsp=0x7fff2690fa8c) at eval.c:14077
> > #10 0x00000000004421cc in f_search (argvars=0x7fff2690fbc0,
> > rettv=0x7fff2690fd80) at eval.c:14120
> > #11 0x0000000000439522 in call_func (name=0x986920 "search", len=6,
> > rettv=0x7fff2690fd80, argcount=2, argvars=0x7fff2690fbc0, firstline=1,
> > lastline=1, doesrange=0x7fff2690fd7c, evaluate=1, selfdict=0x0)
> > at eval.c:7632
> > #12 0x0000000000439043 in get_func_tv (name=0x986920 "search", len=6,
> > rettv=0x7fff2690fd80, arg=0x7fff2690fda0, firstline=1, lastline=1,
> > doesrange=0x7fff2690fd7c, evaluate=1, selfdict=0x0) at eval.c:7450
> > #13 0x0000000000432c73 in ex_call (eap=0x7fff2690fe80) at eval.c:3215
> > #14 0x0000000000463c6b in do_one_cmd (cmdlinep=0x7fff26910528, sourcing=0,
> > cstack=0x7fff26910080, fgetline=0x47821a <getexline>, cookie=0x0)
> > at ex_docmd.c:2623
> > #15 0x000000000046146a in do_cmdline (cmdline=0x0,
> > getline=0x47821a <getexline>, cookie=0x0, flags=0) at ex_docmd.c:1099
> > #16 0x00000000004ebdd2 in nv_colon (cap=0x7fff26910670) at normal.c:5179
> > #17 0x00000000004e4dd8 in normal_cmd (oap=0x7fff26910730, toplevel=1)
> > at normal.c:1152
> > #18 0x00000000004a5be2 in main_loop (cmdwin=0, noexmode=0) at main.c:1181
> > #19 0x00000000004a572e in main (argc=1, argv=0x7fff26910a28) at main.c:940
> >
> > (gdb) up
> > #1 0x000000000050e38d in may_core_dump () at os_unix.c:2950
> > 2950 kill(getpid(), deadly_signal); /* Die using the
> > signal we caught */
> > (gdb)
> > #2 0x000000000050e328 in mch_exit (r=1) at os_unix.c:2915
> > 2915 may_core_dump();
> > (gdb)
> > #3 0x00000000004a5eb3 in getout (exitval=1) at main.c:1342
> > 1342 mch_exit(exitval);
> > (gdb)
> > #4 0x00000000004d2128 in preserve_exit () at misc1.c:8355
> > 8355 getout(1);
> > (gdb)
> > #5 0x000000000050c73d in deathtrap (sigarg=11) at os_unix.c:1030
> > 1030 preserve_exit(); /* preserve files and exit */
> > (gdb)
> > #6 <signal handler called>
> > (gdb)
> > #7 0x00000000004e0b33 in utf_head_off (base=0x9251c4 "c Y",
> > p=0x1009251c3 <Address 0x1009251c3 out of bounds>) at mbyte.c:2480
> > 2480 if (*p < 0x80) /* be quick for ASCII */
> > (gdb) p p
> > $1 = (char_u *) 0x1009251c3 <Address 0x1009251c3 out of bounds>
> >
> > -> pointer 'p' is invalid
> >
> > Valgrind memory checker also detects a problem when
> > doing ":call search('\_s*a\_s*','e')" at the same location
> > on the x86_64 machine (no problem detected on the
> > x86 machine):
> >
> > ==13671== Invalid read of size 1
> > ==13671== at 0x4E0B33: utf_head_off (mbyte.c:2480)
> > ==13671== by 0x539234: searchit (search.c:848)
> > ==13671== by 0x4420E6: search_cmn (eval.c:14077)
> > ==13671== by 0x4421CB: f_search (eval.c:14120)
> > ==13671== by 0x439521: call_func (eval.c:7632)
> > ==13671== by 0x439042: get_func_tv (eval.c:7450)
> > ==13671== by 0x432C72: ex_call (eval.c:3215)
> > ==13671== by 0x463C6A: do_one_cmd (ex_docmd.c:2623)
> > ==13671== by 0x461469: do_cmdline (ex_docmd.c:1099)
> > ==13671== by 0x4EBDD1: nv_colon (normal.c:5179)
> > ==13671== by 0x4E4DD7: normal_cmd (normal.c:1152)
> > ==13671== by 0x4A5BE1: main_loop (main.c:1181)
> > ==13671== by 0x4A572D: main (main.c:940)
> > ==13671== Address 0x10b5e697f is not stack'd, malloc'd or (recently) free'd
> >
> > I can reproduce it 100% of the time.
>
> What is the text you are searching in? I assume your 'encoding' is set
> to "utf-8"?
I'm doing the exact same thing as described in the first email
of this thread, i.e. the buffer contains only 2 lines, the cursor
is on first character X:
X a
c Y
Then I call...
:call search('\_s*a\_s*','e')
... and it crashes as described on one machine (x86_64).
On the other machine (x86), it does not crash but cursor
moves to Y (which is not right either from initial bug submitter).
Encoding is utf-8 on both machines.
I've updated to latest vim-7.1.245 on both hosts with
same results (one works, the other one crashes).
> If you want to do a little digging, check out the code before calling
> mb_head_off(), line 848 in search.c. Especially the value of "endpos"
> compared to what's in the text.
I've put the following debug fprintf(stderr, ...) on line 848 before
call to (*mb_head_off)(...) (without changing line numbers in original
code):
fprintf(stderr, "%s:%d options=0x%x lnum=%ld endpos.lnum=%ld
endpos.col=%d pos->lnum=%ld pos->col=%d buf=%p
buf->b_ml.ml_line_count=%ld ptr=%p *ptr=%d\n", __FILE__, __LINE__,
options, lnum, endpos.lnum, endpos.col, pos->lnum, pos->col, buf,
buf->b_ml.ml_line_count, ptr, *ptr);
... and the following fprintf(stderr, ...) in mbyte.c before
dereferencing p pointer at line mbyte.c:2480:
fprintf(stderr, "%s:%d p=%p\n", __FILE__, __LINE__, p);
On host where it does not crash I see:
search.c:848 options=0x440 lnum=1 endpos.lnum=1 endpos.col=0
pos->lnum=2 pos->col=-1 buf=0x81f3110 buf->b_ml.ml_line_count=2
ptr=0x82feca8 *ptr=99
mbyte.c:2479 p=0x82feca7
On host where it crashes, I see:
search.c:848 options=0x440 lnum=1 endpos.lnum=1 endpos.col=0
pos->lnum=2 pos->col=-1 buf=0x8333f0 buf->b_ml.ml_line_count=2
ptr=0x919a88 *ptr=99
mbyte.c:2479 p=0x100919a87
Ahh! I get it. Notice that pos->col is -1. When doing the pointer
arithmetics at line search.c:848 (ptr + pos->col) something goes terribly
wrong:
0x82feca8 + (-1) -> p=0x82feca7 ... and no crash (that's on the 32 bits Linux)
0x919a88 + (-1) -> 0x100919a87 ... and crash (that's on the 64 bits Linux)
It actually adds 4294967295 to the pointer, instead of removing -1.
type pos pos is:
typedef struct
{
linenr_T lnum; /* line number */
colnr_T col; /* column number */
} lpos_T;
and type of colnr_T is
typedef unsigned colnr_T;
Notice that it's unsigned. So that explains why it adds a large value to the
pointer instead of -1. On the 32 bits host, it works because pointer
wraps around 32 bits. On the 64 bits, pointer does not wrap on 32 bits
hence crash.
I can fix the crash by adding a cast as follows, but I think it's probably
wrong to have column 0 and remove 1 to it in the first place. This cast
is only masking the root cause of the problems:
diff -c -r1.64 search.c
*** search.c 26 Jan 2008 20:15:46 -0000 1.64
--- search.c 12 Feb 2008 09:13:21 -0000
***************
*** 845,851 ****
ptr = (char_u *)"";
else
ptr = ml_get_buf(buf, pos->lnum, FALSE);
! pos->col -= (*mb_head_off)(ptr, ptr + pos->col);
}
#endif
}
--- 845,851 ----
ptr = (char_u *)"";
else
ptr = ml_get_buf(buf, pos->lnum, FALSE);
! pos->col -= (*mb_head_off)(ptr, ptr +
(int)pos->col);
}
#endif
}
-- Dominique
--~--~---------~--~----~------------~-------~--~----~
You received this message from the "vim_dev" maillist.
For more information, visit http://www.vim.org/maillist.php
-~----------~----~----~----~------~----~------~--~---