Hi Valgrind memory checker detects that Vim is using freed memory in the spelling checker code:
==8692== Invalid read of size 1 ==8692== at 0x8199D87: spell_to_word_end (spell.c:15854) ==8692== by 0x8166424: win_line (screen.c:3054) ==8692== by 0x8163AD5: win_update (screen.c:1765) ==8692== by 0x8161C34: update_screen (screen.c:522) ==8692== by 0x8064F1B: ins_redraw (edit.c:1474) ==8692== by 0x8063B96: edit (edit.c:688) ==8692== by 0x812322A: normal_cmd (normal.c:1327) ==8692== by 0x80E5D2D: main_loop (main.c:1181) ==8692== by 0x80E587D: main (main.c:940) ==8692== Address 0x50615F0 is 40 bytes inside a block of size 96 free'd ==8692== at 0x402237F: free (vg_replace_malloc.c:233) ==8692== by 0x8113F55: vim_free (misc2.c:1580) ==8692== by 0x80F864A: ml_flush_line (memline.c:3149) ==8692== by 0x80F69FE: ml_get_buf (memline.c:2111) ==8692== by 0x80F68BB: ml_get (memline.c:2034) ==8692== by 0x818D567: check_need_cap (spell.c:10271) ==8692== by 0x817C828: spell_move_to (spell.c:2098) ==8692== by 0x81663D0: win_line (screen.c:3048) ==8692== by 0x8163AD5: win_update (screen.c:1765) ==8692== by 0x8161C34: update_screen (screen.c:522) ==8692== by 0x8064F1B: ins_redraw (edit.c:1474) ==8692== by 0x8063B96: edit (edit.c:688) ==8692== by 0x812322A: normal_cmd (normal.c:1327) ==8692== by 0x80E5D2D: main_loop (main.c:1181) ==8692== by 0x80E587D: main (main.c:940) (and then follows several more errors) Here is the relevant code in screen.c: 2927 line = ml_get_buf(wp->w_buffer, lnum, FALSE); 2928 ptr = line; .... .... 3037 #ifdef FEAT_SPELL 3038 /* When spell checking a word we need to figure out the start of the 3039 * word and if it's badly spelled or not. */ 3040 if (has_spell) 3041 { 3042 int len; 3043 hlf_T spell_hlf = HLF_COUNT; 3044 3045 pos = wp->w_cursor; 3046 wp->w_cursor.lnum = lnum; 3047 wp->w_cursor.col = (colnr_T)(ptr - line); !!3048 len = spell_move_to(wp, FORWARD, TRUE, TRUE, &spell_hlf); 3049 if (len == 0 || (int)wp->w_cursor.col > ptr - line) 3050 { 3051 /* no bad word found at line start, don't check until end of a 3052 * word */ 3053 spell_hlf = HLF_COUNT; !!3054 word_end = (int)(spell_to_word_end(ptr, wp->w_buffer) - line + 1); 3055 } Error happens inside call of spell_to_word_end() at screen.c:3054 because ptr is dereferenced inside spell_to_word_end() but is pointing to memory which has already been freed (bug!). ptr was previously freed just a few lines above, as a side effect of calling spell_move_to(...) 6 lines above at screen.c:3048, because spell_move_to(...) may in some cases call ml_get(...) which invalidates previous pointer returned by previous call of ml_get(...). So call to spell_move_to invalidates line and ptr which were initialized at line 2927/2928 in screen.c. Here is how I can reproduce the bug: $ valgrind vim -u NONE -c 'set nowrap|set spell|start' -s spell-access-freed-mem.vim 2> valgrind.log spell-testcase is a small file generated randomly which triggers this bug: http://dominique.pelle.free.fr/spell-access-freed-mem.vim But happens only if terminal is small enough (80x25 or smaller) I attach a patch which fixes the bug but please review it. Maybe there is a better solution. I'm using vim-7.1 (Patches 1-242) on Linux x86 in a gnome-terminal, built with "configure --with-feature=huge", without optimizations (-O0 -g). -- 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.98 diff -c -r1.98 screen.c *** screen.c 19 Jan 2008 14:58:17 -0000 1.98 --- screen.c 3 Feb 2008 15:42:20 -0000 *************** *** 2644,2650 **** #if defined(FEAT_SIGNS) || (defined(FEAT_QUICKFIX) && defined(FEAT_WINDOWS)) \ || defined(FEAT_SYN_HL) || defined(FEAT_DIFF) # define LINE_ATTR ! int line_attr = 0; /* atrribute for the whole line */ #endif #ifdef FEAT_SEARCH_EXTRA matchitem_T *cur; /* points to the match list */ --- 2644,2650 ---- #if defined(FEAT_SIGNS) || (defined(FEAT_QUICKFIX) && defined(FEAT_WINDOWS)) \ || defined(FEAT_SYN_HL) || defined(FEAT_DIFF) # define LINE_ATTR ! int line_attr = 0; /* attribute for the whole line */ #endif #ifdef FEAT_SEARCH_EXTRA matchitem_T *cur; /* points to the match list */ *************** *** 3045,3051 **** --- 3045,3060 ---- pos = wp->w_cursor; wp->w_cursor.lnum = lnum; wp->w_cursor.col = (colnr_T)(ptr - line); + + /* Save position in line, since spell_move_to() invalidates + * line and ptr as it may call ml_get() */ + v = (long)(ptr - line); len = spell_move_to(wp, FORWARD, TRUE, TRUE, &spell_hlf); + + /* Get line again and restore ptr */ + line = ml_get_buf(wp->w_buffer, lnum, FALSE); + ptr = line + v; + if (len == 0 || (int)wp->w_cursor.col > ptr - line) { /* no bad word found at line start, don't check until end of a