On 8/22/07, Bram Moolenaar <[EMAIL PROTECTED]> wrote:
> Perhaps you can add a "max_off" variable, set to LineOffset[row] +
> screen_Columns. Then avoid calling mb_off2cells(off) when off is
> max_off - 2 or more.
With your indications, I modified my original patch. My previous
patch actually did not fix all accesses to uninitialized memory.
More errors were reported when writing characters that occupy two
cells at the bottom right of the screen. An easy way to reproduce
it was to type ":" to enter Ex mode, and then type some text till the
final cell of the screen. Valgrind then reported errors. I tried
with single cell characters (ASCII characters for example) as well
as double cell characters (Chinese characters for example).
Since the boolean expressions was already quite complicated, I did
not feel like making it even more complicated by adding some (off
< max_off - 1) as well as (off < max_off - 2). So I broke the
boolean expression into a couple of 'if'. I find it easier to
read it that way. I hope that's OK.
I attach my new patch. Many things in screen.c are still
mysterious to me, so definitely review it to make sure it does not
break anything.
Attached: patch-uninit-mem-access-utf_off2cells-2.txt
Cheers
-- 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 22 Aug 2007 21:51:31 -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;
***************
*** 6183,6189 ****
int col;
int attr;
{
! unsigned off;
char_u *ptr = text;
int c;
#ifdef FEAT_MBYTE
--- 6183,6189 ----
int col;
int attr;
{
! unsigned off, max_off;
char_u *ptr = text;
int c;
#ifdef FEAT_MBYTE
***************
*** 6203,6208 ****
--- 6203,6209 ----
return;
off = LineOffset[row] + col;
+ max_off = LineOffset[row] + screen_Columns;
while (col < screen_Columns
&& (len < 0 || (int)(ptr - text) < len)
&& *ptr != NUL)
***************
*** 6323,6345 ****
* (mb_off2cells() may return 2 on the right halve). */
if (clear_next_cell)
clear_next_cell = FALSE;
! 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)))
! clear_next_cell = TRUE;
/* Make sure we never leave a second byte of a double-byte behind,
* it confuses mb_off2cells(). */
! if (enc_dbcs
! && ((mbyte_cells == 1 && (*mb_off2cells)(off) > 1)
! || (mbyte_cells == 2
! && (*mb_off2cells)(off) == 1
! && (*mb_off2cells)(off + 1) > 1)))
! ScreenLines[off + mbyte_blen] = 0;
#endif
ScreenLines[off] = c;
ScreenAttrs[off] = attr;
--- 6324,6365 ----
* (mb_off2cells() may return 2 on the right halve). */
if (clear_next_cell)
clear_next_cell = FALSE;
! else if (has_mbyte)
! {
! /* If we reach the end of text */
! if (len < 0 ? ptr[mbyte_blen] == NUL
! : ptr + mbyte_blen >= text + len)
! {
! if (mbyte_cells == 1 && off < max_off - 1)
! {
! if ((*mb_off2cells)(off) > 1)
! clear_next_cell = TRUE;
! }
! else if (mbyte_cells == 2 && off < max_off - 2)
! {
! if ((*mb_off2cells)(off) == 1
! && (*mb_off2cells)(off + 1) > 1)
! clear_next_cell = TRUE;
! }
! }
! }
/* Make sure we never leave a second byte of a double-byte behind,
* it confuses mb_off2cells(). */
! if (enc_dbcs)
! {
! if (mbyte_cells == 1 && off < max_off - 1)
! {
! if ((*mb_off2cells)(off) == 1)
! ScreenLines[off + mbyte_blen] = 0;
! }
! else if (mbyte_cells == 2 && off < max_off - 2)
! {
! if ((*mb_off2cells)(off) == 1
! && (*mb_off2cells)(off + 1) > 1)
! ScreenLines[off + mbyte_blen] = 0;
! }
! }
#endif
ScreenLines[off] = c;
ScreenAttrs[off] = attr;