Bug 221

Summary: CTRL-F in Insert mode crashes Vim when encoding=utf-8
Product: Sisyphus Reporter: Sergey Vlasov <vsu>
Component: vim-X11Assignee: Sergey Vlasov <vsu>
Status: CLOSED FIXED QA Contact:
Severity: minor    
Priority: P4 CC: admsasha, glebfm, ldv
Version: unstable   
Hardware: all   
OS: Linux   

Description Sergey Vlasov 2001-12-10 20:26:22 MSK
(This bug report was already sent to <a href="mailto:bugs@vim.org" target="_new">bugs@vim.org</a>)

I have found a bug in Vim 6.0.093: using &lt;CTRL-F&gt; in Insert mode
to reindent the current line causes a crash or hang when

Steps to reproduce:

1. Create \&quot;test-gvimrc.vim\&quot; with the following text:

\&quot; start of test-gvimrc.vim
let &amp;termencoding=&amp;encoding
set encoding=utf-8
let &amp;fileencodings=\'ucs-bom,utf-8,\'.&amp;termencoding
set guifont=-*-courier-medium-r-normal--*-140-*-*-*-*-iso10646-1
set cindent
\&quot; end of test-gvimrc.vim

2. Create a test file \&quot;test.c\&quot; with the contents described by
the C string \&quot;{\\n \\n\&quot; - just two lines, first with \'{\', second
with a space.

3. Run:

gvim -u NONE -U test-gvimrc.vim test.c

(or gdb gvim; set args -f -u NONE -U test-gvimrc.vim test.c; run)

4. Type:


After doing this gvim gets SIGSEGV:

$ gdb /home/vsu/RPM/BUILD/vim60/src/gvim
(gdb) set args -f -u NONE -U test-gvimrc.vim test.c
(gdb) r
Starting program: /home/vsu/RPM/BUILD/vim60/src/gvim -f -u NONE -U test-gvimrc.vim test.c
[New Thread 1024 (LWP 5404)]

Program received signal SIGSEGV, Segmentation fault.
[Switching to Thread 1024 (LWP 5404)]
0x40425885 in memmove (dest=0x8227040, src=0x82dd4c0, len=4294967292)
    at ../sysdeps/generic/memmove.c:105
105     ../sysdeps/generic/memmove.c: No such file or directory.
(gdb) where
#0  0x40425885 in memmove (dest=0x8227040, src=0x82dd4c0, len=4294967292)
    at ../sysdeps/generic/memmove.c:105
#1  0x80d0752 in ins_str (s=0x825a920 \&quot; \&quot;) at misc1.c:1762
#2  0x8079836 in change_indent (type=1, amount=8, round=0, replaced=0)
    at edit.c:1537
#3  0x807e1ba in fixthisline (get_the_indent=0x80d3570 &lt;get_c_indent&gt;)
    at edit.c:5039
#4  0x80d285d in do_c_expr_indent () at misc1.c:3900
#5  0x8079389 in edit (cmdchar=105, startln=0, count=1) at edit.c:1243
#6  0x80ea148 in nv_edit (cap=0xbffff400) at normal.c:7641
#7  0x80e13f2 in normal_cmd (oap=0xbffff470, toplevel=1) at normal.c:1036
#8  0x80bcaee in main_loop (cmdwin=0) at main.c:1976
#9  0x80bc861 in main (argc=0, argv=0xbffff624) at main.c:1831
#10 0x403c2971 in __libc_start_main (main=0x80bad90 &lt;main&gt;, argc=7, 
    ubp_av=0xbffff624, init=0x806aa2c &lt;_init&gt;, fini=0x81a3b40 &lt;_fini&gt;, 
    rtld_fini=0x4000cd74 &lt;_dl_fini&gt;, stack_end=0xbffff61c)
    at ../sysdeps/generic/libc-start.c:129

At this point most of the data is already trashed by memmove():
when running without gdb, on my system it appears that gvim
hangs -- really it keeps getting SIGSEGV inside a SIGSEGV

Seems that the problem is in change_indent(): when it tries to
advance the cursor to the right screen column, in multibyte mode
it calls (*mb_ptr2len_check)(ptr + new_cursor_col) after ptr =
ml_get_curline() and new_cursor_col = -1, so (ptr +
new_cursor_col) points to garbage before the line contents.  On
my system this is usually \'\\0\', so (*mb_ptr2len_check)() in
utf-8 mode returns 0, which in the end leads to
curwin-&gt;w_cursor.col = -1, which then confuses ins_str().

This small patch fixes the problem:

--- src/edit.c.utfindent	Sat Dec  8 16:19:59 2001
+++ src/edit.c	Sat Dec  8 17:21:56 2001
@@ -1510,7 +1510,7 @@
 	    last_vcol = vcol;
 #ifdef FEAT_MBYTE
-	    if (has_mbyte)
+	    if (has_mbyte &amp;&amp; new_cursor_col &gt;= 0)
 		new_cursor_col += (*mb_ptr2len_check)(ptr + new_cursor_col);



Comment 1 Sergey Vlasov 2002-07-12 17:21:04 MSD
Fixed in upstream
Comment 2 Sergey Vlasov 2002-07-12 17:21:04 MSD
Fixed in upstream