Dominique Pelle wrote:
> Valgrind memory checker detects the following access to uninitialized
> memory:
>
> ==15698== Conditional jump or move depends on uninitialised value(s)
> ==15698== at 0x811CC12: utfc_ptr2len (mbyte.c:1709)
> ==15698== by 0x805CB9F: str_foldcase (charset.c:493)
> ==15698== by 0x819AEDE: check_keyword_id (syntax.c:3192)
> ==15698== by 0x8198DD9: syn_current_attr (syntax.c:1907)
> ==15698== by 0x8198B19: get_syntax_attr (syntax.c:1771)
> ==15698== by 0x8165729: win_line (screen.c:3895)
> ==15698== by 0x81614E5: win_update (screen.c:1765)
> ==15698== by 0x815F6F0: update_screen (screen.c:522)
> ==15698== by 0x80D4CD6: vgetorpeek (getchar.c:2672)
> ==15698== by 0x80D396F: vgetc (getchar.c:1710)
> ==15698== by 0x80D3A15: safe_vgetc (getchar.c:1757)
> ==15698== by 0x8063FB0: edit (edit.c:711)
> ==15698== by 0x812DDB0: invoke_edit (normal.c:8813)
> ==15698== by 0x812DD56: nv_edit (normal.c:8786)
> ==15698== by 0x81216DE: normal_cmd (normal.c:1152)
> ==15698== by 0x80E4E2E: main_loop (main.c:1177)
> ==15698== by 0x80E497E: main (main.c:936)
> (...then follow many other errors...)
>
> I can reproduce it 100% of the time but the way to reproduce it
> is too complicated to attempt to explain it here. I have not found
> a simpler test case. Attached patch should hopefully suffice to
> clarify the problem anyway.
>
> The code in charset.c is:
>
> 447 #ifdef FEAT_MBYTE
> 448 if (enc_utf8 || (has_mbyte && MB_BYTE2LEN(STR_CHAR(i)) > 1))
> 449 {
> 450 if (enc_utf8)
> 451 {
> 452 int c, lc;
> 453
> 454 c = utf_ptr2char(STR_PTR(i));
> 455 lc = utf_tolower(c);
> 456 if (c != lc)
> 457 {
> 458 int ol = utf_char2len(c);
> 459 int nl = utf_char2len(lc);
> 460
> 461 /* If the byte length changes need to shift the following
> 462 * characters forward or backward. */
> 463 if (ol != nl)
> 464 {
> 465 if (nl > ol)
> 466 {
> 467 if (buf == NULL ? ga_grow(&ga, nl - ol + 1) ==
> FAIL
> 468 : len + nl - ol >=
> buflen)
> 469 {
> 470 /* out of memory, keep old char */
> 471 lc = c;
> 472 nl = ol;
> 473 }
> 474 }
> 475 if (ol != nl)
> 476 {
> 477 if (buf == NULL)
> 478 {
> 479 STRMOVE(GA_PTR(i) + nl, GA_PTR(i) + ol);
> 480 ga.ga_len += nl - ol;
> 481 }
> 482 else
> 483 {
> 484 STRMOVE(buf + i + nl, buf + i + ol);
> 485 len += nl - ol;
> 486 }
> 487 }
> 488 }
> !489 (void)utf_char2bytes(lc, STR_PTR(i));
> 490 }
> 491 }
> 492 /* skip to next multi-byte char */
> !493 i += (*mb_ptr2len)(STR_PTR(i));
> 494 }
> 495 else
> 496 #endif
>
>
> Bug happens when string STR_PTR(i) contains a truncated utf-8 sequence. In
> that case, utf_ptr2char(STR_PTR(i)) at line 454 returns only the first byte
> of the truncated utf-8 sequence. If this first byte is >= 0x80, then
> utf_char2len(c) at line 458 sets 'ol' to something > 1 (which is
> inconsistent with the fact that line 454 only returned the first byte).
> Then call to utf_char2bytes(lc, STR_PTR(i)) at line 489 can write
> multiple bytes, hence overwriting NUL end of string and then function
> keep accessing several bytes beyond end of string (which is uninitialized).
>
> Attached patch fixes it. It uses utf_ptr2len(STR_PTR(i)) rather than
> utf_char2len(c) to compute the length of the utf-8 sequence, so invalid
> utf-8 sequence can be detected and skipped (converting case for invalid
> utf-8 sequence does not make sense anyway).
>
> I'm using Vim-7.2a BETA (huge) with patches 1-5 on Linux x86, utf-8 locale.
Thanks for finding and fixing this. I'll include it. With a shorter
comment though.
--
Laughing helps. It's like jogging on the inside.
/// Bram Moolenaar -- [EMAIL PROTECTED] -- http://www.Moolenaar.net \\\
/// sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\
\\\ download, build and distribute -- http://www.A-A-P.org ///
\\\ help me help AIDS victims -- http://ICCF-Holland.org ///
--~--~---------~--~----~------------~-------~--~----~
You received this message from the "vim_dev" maillist.
For more information, visit http://www.vim.org/maillist.php
-~----------~----~----~----~------~----~------~--~---