ngollan wrote:
> When pasting a high unicode character (>uFFFF) into vim, the program
> sometimes crashes from a SIGFPE.
>
> I'm running vim from Debian testing on amd64.
>
> ===== Example character:
> http://www.fileformat.info/info/unicode/char/1f638/index.htm
Hi
I can reproduce it with Vim-7.3.364 on Linux. Just opening a
file containing Unicode character 0x1f638 makes Vim crash.
I see that the binary search fails to find a range in function utf_convert(...):
vim/src/mbytes.c:
2761 utf_convert(a, table, tableSize)
2762 int a;
2763 convertStruct table[];
2764 int tableSize;
2765 {
2766 int start, mid, end; /* indices into table */
2767
2768 start = 0;
2769 end = tableSize / sizeof(convertStruct);
2770 while (start < end)
2771 {
2772 /* need to search further */
2773 mid = (end + start) /2;
2774 if (table[mid].rangeEnd < a)
2775 start = mid + 1;
2776 else
2777 end = mid;
2778 }
2779 if (table[start].rangeStart <= a && a <= table[start].rangeEnd
2780 && (a - table[start].rangeStart) % table[start].step == 0)
2781 return (a + table[start].offset);
2782 else
2783 return a;
2784 }
The start, mid, end variables in utf_convert evolve as follow
during the binary search:
start=0 mid=78 end=156
start=79 mid=117 end=156
start=118 mid=137 end=156
start=138 mid=147 end=156
start=148 mid=152 end=156
start=153 mid=154 end=156
start=155 mid=155 end=156
start=156 mid=155 end=156
Then at line mbytes.c:2779, table[start] it used
which accesses beyond the end of foldCase[] array.
Interestingly, Valgrind memory checker does
not detect this (since it's an overflow in a
global variable) but the address-sanitizer tool
available at...
http://code.google.com/p/address-sanitizer/
... does detect it and says:
READ of size 4 at 0x000000afc440 thread T0
#0 0x5e63c2 in utf_convert mbyte.c:0
#1 0x670dbf in vim_regexec_both regexp.c:0
#2 0x67110c in vim_regexec_nl ??:0
#3 0x4bdb86 in eval4 eval.c:0
#4 0x4bcc94 in eval3 eval.c:0
#5 0x4bc844 in eval2 eval.c:0
#6 0x47b7be in eval1 eval.c:0
#7 0x47af5e in eval0 eval.c:0
#8 0x47aa29 in eval_to_bool ??:0
#9 0x50f644 in ex_if ??:0
#10 0x4efc7a in do_one_cmd ex_docmd.c:0
#11 0x4e9383 in do_cmdline ??:0
#12 0x4e6253 in do_source ??:0
#13 0x4e506a in do_in_runtimepath ??:0
#14 0x4efc7a in do_one_cmd ex_docmd.c:0
#15 0x4e9383 in do_cmdline ??:0
#16 0x54340e in apply_autocmds_group fileio.c:0
#17 0x53361f in apply_autocmds_exarg fileio.c:0
#18 0x532d94 in readfile ??:0
#19 0x4321cc in open_buffer ??:0
#20 0x7bc94a in create_windows main.c:0
#21 0x7b7582 in main ??:0
#22 0x7faffcdaed8e in __libc_start_main
/build/buildd/eglibc-2.12.1/csu/libc-start.c:258
#23 0x431e19 in _start ??:0
0x000000afc440 is located 0 bytes to the right of global variable
'foldCase' (0xafba80) of size 2496
Attached patch fixes the crash.
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
diff -r 749c0a60b745 src/mbyte.c
--- a/src/mbyte.c Thu Dec 01 20:59:21 2011 +0100
+++ b/src/mbyte.c Tue Dec 06 16:28:08 2011 +0100
@@ -2776,7 +2776,8 @@
else
end = mid;
}
- if (table[start].rangeStart <= a && a <= table[start].rangeEnd
+ if (start < tableSize / sizeof(convertStruct)
+ && table[start].rangeStart <= a && a <= table[start].rangeEnd
&& (a - table[start].rangeStart) % table[start].step == 0)
return (a + table[start].offset);
else