Hi
Valgrind memory checker reports the following error:
==10724== Conditional jump or move depends on uninitialized value(s)
==10724== at 0x810A1EB: utf_off2cells (mbyte.c:1338)
==10724== by 0x815265C: screen_puts_len (screen.c:6326)
==10724== by 0x80EE251: screen_puts_mbyte (message.c:1684)
==10724== by 0x80EE6FE: msg_puts_display (message.c:1907)
==10724== by 0x80EE4B7: msg_puts_attr_len (message.c:1819)
==10724== by 0x80EE3F9: msg_puts_attr (message.c:1767)
==10724== by 0x80EE2E5: msg_puts (message.c:1717)
==10724== by 0x81A4A3A: version_msg (version.c:1184)
==10724== by 0x81A499C: list_version (version.c:1151)
==10724== by 0x81A46DC: ex_version (version.c:876)
==10724== by 0x809A1FB: do_one_cmd (ex_docmd.c:2622)
==10724== by 0x8097B18: do_cmdline (ex_docmd.c:1100)
==10724== by 0x80971E6: do_cmdline_cmd (ex_docmd.c:706)
==10724== by 0x80D752C: exe_commands (main.c:2638)
==10724== by 0x80D54F6: main (main.c:874)
Error can be reproduced by simply running the ":version"
command with the following conditions:
- vim must be built with multi-byte support (error does not
happen without multi-byte support)
- terminal must be small (4 lines or less). Error does
not happen in terminal larger than 4 lines.
In a small xterm 80 columns x 4 lines, I can get the
error with the following command:
valgrind --num-callers=18 ./vim -u NONE -c ':version' 2> vg.log
The relevant code is:
mbyte.c:
1334 int
1335 utf_off2cells(off)
1336 unsigned off;
1337 {
!!1338 return ScreenLines[off + 1] == 0 ? 2 : 1;
1339 }
By adding some printf, I can see that 'off' parameter is
initialized, but ScreenLines[off + 1] is uninitialized
when accessed at line mbyte.c:1338.
Adding some printf(), I can see that when error happens,
off value is 319, so line mbyte.c:1338 accesses ScreenLines[320]
which is uninitialized. 320 happens to match the size of my
small terminal 80x4 = 320).
>From what I understand (I could be wrong), some Unicode characters
may occupies two cells on the screen. I'm not sure what happens
if such character was in the last cell of the screen (bottom
right of terminal) or if such character was in the last column
of any row of the screen. It looks like function utf_off2cells()
accesses one cell beyond the screen to check for double cell
Unicode characters.
I also see that function screen_char_2() which writes into the
screen ScreenLines[] handles last character of the screen
specially to avoid scroll up (it avoids writing in last
character).
I can fix the error reported by valgrind with the attached
patch, but I do not understand screen.c enough to say whether
it's the correct approach or not.
I can also reproduce the same kind of error in a bigger terminal
when running cscope queries which result in lots of matches such
as ":cs find e e" with cscope database of vim source tree for
example (then pressing spaces several times to see results).
Using a 80x24 terminal, the error then happens with off=1919
(which again corresponds to number of characters in terminal
(80x24 = 1920):
==21069== Conditional jump or move depends on uninitialised value(s)
==21069== at 0x8101643: utf_off2cells (mbyte.c:1338)
==21069== by 0x8147550: screen_puts_len (screen.c:6326)
==21069== by 0x80E5958: screen_puts_mbyte (message.c:1684)
==21069== by 0x80E5D3F: msg_puts_display (message.c:1907)
==21069== by 0x80E5B86: msg_puts_attr_len (message.c:1819)
==21069== by 0x80E51D1: msg_outtrans_len_attr (message.c:1383)
==21069== by 0x80E5AA6: msg_puts_long_len_attr (message.c:1756)
==21069== by 0x80E5A0E: msg_puts_long_attr (message.c:1737)
==21069== by 0x80CFF6B: cs_print_tags_priv (if_cscope.c:1987)
==21069== by 0x80CF477: cs_manage_matches (if_cscope.c:1626)
==21069== by 0x80CD228: cs_print_tags (if_cscope.c:291)
==21069== by 0x8181DCB: do_tag (tag.c:599)
==21069== by 0x80CE872: cs_find_common (if_cscope.c:1158)
==21069== by 0x80CE2E9: cs_find (if_cscope.c:970)
==21069== by 0x80CCED2: do_cscope_general (if_cscope.c:137)
==21069== by 0x80CCF01: do_cscope (if_cscope.c:152)
==21069== by 0x80964AF: do_one_cmd (ex_docmd.c:2622)
==21069== by 0x8093E3D: do_cmdline (ex_docmd.c:1100)
==21069== by 0x810ADD5: nv_colon (normal.c:5168)
I use vim-7.1 (patches 1-87) configured with
--enable-multibyte and --enable-cscope compiled
without optimization (-g -O0) on Linux x86.
Attached: patch-uninit-mem-access-utf_off2cells.txt
-- Dominique
--~--~---------~--~----~------------~-------~--~----~
You received this message from the "vim_dev" maillist.
For more information, visit http://www.vim.org/maillist.php
-~----------~----~----~----~------~----~------~--~---
Index: screen.c
===================================================================
RCS file: /cvsroot/vim/vim7/src/screen.c,v
retrieving revision 1.92
diff -c -r1.92 screen.c
*** screen.c 5 Aug 2007 18:10:49 -0000 1.92
--- screen.c 21 Aug 2007 22:18:24 -0000
***************
*** 1024,1030 ****
type = VALID;
}
! /* Trick: we want to avoid clearning the screen twice. screenclear() will
* set "screen_cleared" to TRUE. The special value MAYBE (which is still
* non-zero and thus not FALSE) will indicate that screenclear() was not
* called. */
--- 1024,1030 ----
type = VALID;
}
! /* Trick: we want to avoid clearing the screen twice. screenclear() will
* set "screen_cleared" to TRUE. The special value MAYBE (which is still
* non-zero and thus not FALSE) will indicate that screenclear() was not
* called. */
***************
*** 4632,4638 ****
/*
* At end of screen line and there is more to come: Display the line
! * so far. If there is no more to display it is catched above.
*/
if ((
#ifdef FEAT_RIGHTLEFT
--- 4632,4638 ----
/*
* At end of screen line and there is more to come: Display the line
! * so far. If there is no more to display it is caught above.
*/
if ((
#ifdef FEAT_RIGHTLEFT
***************
*** 5369,5375 ****
static int skip_status_match_char __ARGS((expand_T *xp, char_u *s));
/*
! * Get the lenght of an item as it will be shown in the status line.
*/
static int
status_match_len(xp, s)
--- 5369,5375 ----
static int skip_status_match_char __ARGS((expand_T *xp, char_u *s));
/*
! * Get the length of an item as it will be shown in the status line.
*/
static int
status_match_len(xp, s)
***************
*** 5435,5441 ****
int row;
char_u *buf;
int len;
! int clen; /* lenght in screen cells */
int fillchar;
int attr;
int i;
--- 5435,5441 ----
int row;
char_u *buf;
int len;
! int clen; /* length in screen cells */
int fillchar;
int attr;
int i;
***************
*** 6326,6332 ****
else if (has_mbyte
&& (len < 0 ? ptr[mbyte_blen] == NUL
: ptr + mbyte_blen >= text + len)
! && ((mbyte_cells == 1 && (*mb_off2cells)(off) > 1)
|| (mbyte_cells == 2
&& (*mb_off2cells)(off) == 1
&& (*mb_off2cells)(off + 1) > 1)))
--- 6326,6334 ----
else if (has_mbyte
&& (len < 0 ? ptr[mbyte_blen] == NUL
: ptr + mbyte_blen >= text + len)
! && ((mbyte_cells == 1
! && off < screen_Columns*screen_Rows - 1
! && (*mb_off2cells)(off) > 1)
|| (mbyte_cells == 2
&& (*mb_off2cells)(off) == 1
&& (*mb_off2cells)(off + 1) > 1)))