diff --git a/7.2.080 b/7.2.080 new file mode 100644 index 0000000..399f9e1 --- /dev/null +++ b/7.2.080 @@ -0,0 +1,365 @@ +To: vim-dev@vim.org +Subject: Patch 7.2.080 +Fcc: outbox +From: Bram Moolenaar +Mime-Version: 1.0 +Content-Type: text/plain; charset=ISO-8859-1 +Content-Transfer-Encoding: 8bit +------------ + +Patch 7.2.080 +Problem: When typing a composing character just after starting completion + may access memory before its allocation point. (Dominique Pelle) +Solution: Don't delete before the completion start column. Add extra checks + for the offset not being negative. +Files: src/edit.c + + +*** ../vim-7.2.079/src/edit.c Wed Aug 6 18:56:55 2008 +--- src/edit.c Tue Jan 13 12:05:57 2009 +*************** +*** 147,152 **** +--- 147,153 ---- + static int ins_compl_bs __ARGS((void)); + static void ins_compl_new_leader __ARGS((void)); + static void ins_compl_addleader __ARGS((int c)); ++ static int ins_compl_len __ARGS((void)); + static void ins_compl_restart __ARGS((void)); + static void ins_compl_set_original_text __ARGS((char_u *str)); + static void ins_compl_addfrommatch __ARGS((void)); +*************** +*** 197,203 **** + static void mb_replace_pop_ins __ARGS((int cc)); + #endif + static void replace_flush __ARGS((void)); +! static void replace_do_bs __ARGS((void)); + #ifdef FEAT_CINDENT + static int cindent_on __ARGS((void)); + #endif +--- 198,205 ---- + static void mb_replace_pop_ins __ARGS((int cc)); + #endif + static void replace_flush __ARGS((void)); +! static void replace_do_bs __ARGS((int limit_col)); +! static int del_char_after_col __ARGS((int limit_col)); + #ifdef FEAT_CINDENT + static int cindent_on __ARGS((void)); + #endif +*************** +*** 1933,1938 **** +--- 1935,1942 ---- + /* + * Backspace the cursor until the given column. Handles REPLACE and VREPLACE + * modes correctly. May also be used when not in insert mode at all. ++ * Will attempt not to go before "col" even when there is a composing ++ * character. + */ + void + backspace_until_column(col) +*************** +*** 1942,1954 **** + { + curwin->w_cursor.col--; + if (State & REPLACE_FLAG) +! replace_do_bs(); +! else +! (void)del_char(FALSE); + } + } + #endif + + #if defined(FEAT_INS_EXPAND) || defined(PROTO) + /* + * CTRL-X pressed in Insert mode. +--- 1946,1994 ---- + { + curwin->w_cursor.col--; + if (State & REPLACE_FLAG) +! replace_do_bs(col); +! else if (!del_char_after_col(col)) +! break; + } + } + #endif + ++ /* ++ * Like del_char(), but make sure not to go before column "limit_col". ++ * Only matters when there are composing characters. ++ * Return TRUE when something was deleted. ++ */ ++ static int ++ del_char_after_col(limit_col) ++ int limit_col; ++ { ++ #ifdef FEAT_MBYTE ++ if (enc_utf8 && limit_col >= 0) ++ { ++ int ecol = curwin->w_cursor.col + 1; ++ ++ /* Make sure the cursor is at the start of a character, but ++ * skip forward again when going too far back because of a ++ * composing character. */ ++ mb_adjust_cursor(); ++ while (curwin->w_cursor.col < limit_col) ++ { ++ int l = utf_ptr2len(ml_get_cursor()); ++ ++ if (l == 0) /* end of line */ ++ break; ++ curwin->w_cursor.col += l; ++ } ++ if (*ml_get_cursor() == NUL || curwin->w_cursor.col == ecol) ++ return FALSE; ++ del_bytes((long)(ecol - curwin->w_cursor.col), FALSE, TRUE); ++ } ++ else ++ #endif ++ (void)del_char(FALSE); ++ return TRUE; ++ } ++ + #if defined(FEAT_INS_EXPAND) || defined(PROTO) + /* + * CTRL-X pressed in Insert mode. +*************** +*** 2418,2424 **** + { + had_match = (curwin->w_cursor.col > compl_col); + ins_compl_delete(); +! ins_bytes(compl_leader + curwin->w_cursor.col - compl_col); + ins_redraw(FALSE); + + /* When the match isn't there (to avoid matching itself) remove it +--- 2458,2464 ---- + { + had_match = (curwin->w_cursor.col > compl_col); + ins_compl_delete(); +! ins_bytes(compl_leader + ins_compl_len()); + ins_redraw(FALSE); + + /* When the match isn't there (to avoid matching itself) remove it +*************** +*** 2470,2476 **** + *p = NUL; + had_match = (curwin->w_cursor.col > compl_col); + ins_compl_delete(); +! ins_bytes(compl_leader + curwin->w_cursor.col - compl_col); + ins_redraw(FALSE); + + /* When the match isn't there (to avoid matching itself) remove it +--- 2510,2516 ---- + *p = NUL; + had_match = (curwin->w_cursor.col > compl_col); + ins_compl_delete(); +! ins_bytes(compl_leader + ins_compl_len()); + ins_redraw(FALSE); + + /* When the match isn't there (to avoid matching itself) remove it +*************** +*** 3209,3215 **** + { + ins_compl_del_pum(); + ins_compl_delete(); +! ins_bytes(compl_leader + curwin->w_cursor.col - compl_col); + compl_used_match = FALSE; + + if (compl_started) +--- 3249,3255 ---- + { + ins_compl_del_pum(); + ins_compl_delete(); +! ins_bytes(compl_leader + ins_compl_len()); + compl_used_match = FALSE; + + if (compl_started) +*************** +*** 3264,3269 **** +--- 3304,3323 ---- + } + + /* ++ * Return the length of the completion, from the completion start column to ++ * the cursor column. Making sure it never goes below zero. ++ */ ++ static int ++ ins_compl_len() ++ { ++ int off = curwin->w_cursor.col - compl_col; ++ ++ if (off < 0) ++ return 0; ++ return off; ++ } ++ ++ /* + * Append one character to the match leader. May reduce the number of + * matches. + */ +*************** +*** 3621,3630 **** + { + ins_compl_delete(); + if (compl_leader != NULL) +! ins_bytes(compl_leader + curwin->w_cursor.col - compl_col); + else if (compl_first_match != NULL) +! ins_bytes(compl_orig_text +! + curwin->w_cursor.col - compl_col); + retval = TRUE; + } + +--- 3675,3683 ---- + { + ins_compl_delete(); + if (compl_leader != NULL) +! ins_bytes(compl_leader + ins_compl_len()); + else if (compl_first_match != NULL) +! ins_bytes(compl_orig_text + ins_compl_len()); + retval = TRUE; + } + +*************** +*** 4256,4262 **** + static void + ins_compl_insert() + { +! ins_bytes(compl_shown_match->cp_str + curwin->w_cursor.col - compl_col); + if (compl_shown_match->cp_flags & ORIGINAL_TEXT) + compl_used_match = FALSE; + else +--- 4309,4315 ---- + static void + ins_compl_insert() + { +! ins_bytes(compl_shown_match->cp_str + ins_compl_len()); + if (compl_shown_match->cp_flags & ORIGINAL_TEXT) + compl_used_match = FALSE; + else +*************** +*** 4425,4431 **** + if (!compl_get_longest || compl_used_match) + ins_compl_insert(); + else +! ins_bytes(compl_leader + curwin->w_cursor.col - compl_col); + } + else + compl_used_match = FALSE; +--- 4478,4484 ---- + if (!compl_get_longest || compl_used_match) + ins_compl_insert(); + else +! ins_bytes(compl_leader + ins_compl_len()); + } + else + compl_used_match = FALSE; +*************** +*** 7123,7131 **** + * cc == 0: character was inserted, delete it + * cc > 0: character was replaced, put cc (first byte of original char) back + * and check for more characters to be put back + */ + static void +! replace_do_bs() + { + int cc; + #ifdef FEAT_VREPLACE +--- 7176,7187 ---- + * cc == 0: character was inserted, delete it + * cc > 0: character was replaced, put cc (first byte of original char) back + * and check for more characters to be put back ++ * When "limit_col" is >= 0, don't delete before this column. Matters when ++ * using composing characters, use del_char_after_col() instead of del_char(). + */ + static void +! replace_do_bs(limit_col) +! int limit_col; + { + int cc; + #ifdef FEAT_VREPLACE +*************** +*** 7153,7159 **** + #ifdef FEAT_MBYTE + if (has_mbyte) + { +! del_char(FALSE); + # ifdef FEAT_VREPLACE + if (State & VREPLACE_FLAG) + orig_len = (int)STRLEN(ml_get_cursor()); +--- 7209,7215 ---- + #ifdef FEAT_MBYTE + if (has_mbyte) + { +! (void)del_char_after_col(limit_col); + # ifdef FEAT_VREPLACE + if (State & VREPLACE_FLAG) + orig_len = (int)STRLEN(ml_get_cursor()); +*************** +*** 7203,7209 **** + changed_bytes(curwin->w_cursor.lnum, curwin->w_cursor.col); + } + else if (cc == 0) +! (void)del_char(FALSE); + } + + #ifdef FEAT_CINDENT +--- 7259,7265 ---- + changed_bytes(curwin->w_cursor.lnum, curwin->w_cursor.col); + } + else if (cc == 0) +! (void)del_char_after_col(limit_col); + } + + #ifdef FEAT_CINDENT +*************** +*** 8239,8245 **** + * Replace mode */ + if (curwin->w_cursor.lnum != Insstart.lnum + || curwin->w_cursor.col >= Insstart.col) +! replace_do_bs(); + } + else + (void)del_char(FALSE); +--- 8295,8301 ---- + * Replace mode */ + if (curwin->w_cursor.lnum != Insstart.lnum + || curwin->w_cursor.col >= Insstart.col) +! replace_do_bs(-1); + } + else + (void)del_char(FALSE); +*************** +*** 8556,8562 **** + break; + } + if (State & REPLACE_FLAG) +! replace_do_bs(); + else + { + #ifdef FEAT_MBYTE +--- 8612,8618 ---- + break; + } + if (State & REPLACE_FLAG) +! replace_do_bs(-1); + else + { + #ifdef FEAT_MBYTE +*** ../vim-7.2.079/src/version.c Tue Jan 6 16:13:42 2009 +--- src/version.c Tue Jan 13 12:25:29 2009 +*************** +*** 678,679 **** +--- 678,681 ---- + { /* Add new patch number below this line */ ++ /**/ ++ 80, + /**/ + +-- +At some point in the project somebody will start whining about the need to +determine the project "requirements". This involves interviewing people who +don't know what they want but, curiously, know exactly when they need it. + (Scott Adams - The Dilbert principle) + + /// Bram Moolenaar -- Bram@Moolenaar.net -- 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 ///