To: vim-dev@vim.org Subject: Patch 7.2.200 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ Patch 7.2.200 Problem: Reading past end of string when navigating the menu bar or resizing the window. Solution: Add and use mb_ptr2len_len(). (partly by Dominique Pelle) Also add mb_ptr2cells_len() to prevent more trouble. Files: src/gui_gtk_x11.c, src/os_unix.c, src/globals.h, src/mbyte.c, src/proto/mbyte.pro *** ../vim-7.2.199/src/gui_gtk_x11.c 2009-06-03 16:20:09.000000000 +0200 --- src/gui_gtk_x11.c 2009-06-16 14:44:19.000000000 +0200 *************** *** 6077,6088 **** # ifdef FEAT_MBYTE if (enc_utf8) { ! c = utf_ptr2char(p); if (c >= 0x10000) /* show chars > 0xffff as ? */ c = 0xbf; buf[textlen].byte1 = c >> 8; buf[textlen].byte2 = c; ! p += utf_ptr2len(p); width += utf_char2cells(c); } else --- 6135,6149 ---- # ifdef FEAT_MBYTE if (enc_utf8) { ! int pcc[MAX_MCO]; ! ! /* TODO: use the composing characters */ ! c = utfc_ptr2char_len(p, &pcc, len - (p - s)); if (c >= 0x10000) /* show chars > 0xffff as ? */ c = 0xbf; buf[textlen].byte1 = c >> 8; buf[textlen].byte2 = c; ! p += utfc_ptr2len_len(p, len - (p - s)); width += utf_char2cells(c); } else *************** *** 6106,6113 **** if (has_mbyte) { width = 0; ! for (p = s; p < s + len; p += (*mb_ptr2len)(p)) ! width += (*mb_ptr2cells)(p); } else # endif --- 6167,6174 ---- if (has_mbyte) { width = 0; ! for (p = s; p < s + len; p += (*mb_ptr2len_len)(p, len - (p - s))) ! width += (*mb_ptr2cells_len)(p, len - (p - s)); } else # endif *** ../vim-7.2.199/src/os_unix.c 2009-05-17 13:30:58.000000000 +0200 --- src/os_unix.c 2009-06-03 12:35:59.000000000 +0200 *************** *** 4305,4311 **** ta_buf[i] = '\n'; # ifdef FEAT_MBYTE if (has_mbyte) ! i += (*mb_ptr2len)(ta_buf + i) - 1; # endif } --- 4305,4312 ---- ta_buf[i] = '\n'; # ifdef FEAT_MBYTE if (has_mbyte) ! i += (*mb_ptr2len_len)(ta_buf + i, ! ta_len + len - i) - 1; # endif } *** ../vim-7.2.199/src/globals.h 2009-06-10 18:15:49.000000000 +0200 --- src/globals.h 2009-06-12 21:10:30.000000000 +0200 *************** *** 810,820 **** --- 815,828 ---- */ /* length of char in bytes, including following composing chars */ EXTERN int (*mb_ptr2len) __ARGS((char_u *p)) INIT(= latin_ptr2len); + /* idem, with limit on string length */ + EXTERN int (*mb_ptr2len_len) __ARGS((char_u *p, int size)) INIT(= latin_ptr2len_len); /* byte length of char */ EXTERN int (*mb_char2len) __ARGS((int c)) INIT(= latin_char2len); /* convert char to bytes, return the length */ EXTERN int (*mb_char2bytes) __ARGS((int c, char_u *buf)) INIT(= latin_char2bytes); EXTERN int (*mb_ptr2cells) __ARGS((char_u *p)) INIT(= latin_ptr2cells); + EXTERN int (*mb_ptr2cells_len) __ARGS((char_u *p, int size)) INIT(= latin_ptr2cells_len); EXTERN int (*mb_char2cells) __ARGS((int c)) INIT(= latin_char2cells); EXTERN int (*mb_off2cells) __ARGS((unsigned off, unsigned max_off)) INIT(= latin_off2cells); EXTERN int (*mb_ptr2char) __ARGS((char_u *p)) INIT(= latin_ptr2char); *** ../vim-7.2.199/src/mbyte.c 2009-05-17 13:30:58.000000000 +0200 --- src/mbyte.c 2009-06-16 15:01:30.000000000 +0200 *************** *** 127,133 **** --- 127,136 ---- static int dbcs_char2len __ARGS((int c)); static int dbcs_char2bytes __ARGS((int c, char_u *buf)); static int dbcs_ptr2len __ARGS((char_u *p)); + static int dbcs_ptr2len_len __ARGS((char_u *p, int size)); + static int utf_ptr2cells_len __ARGS((char_u *p, int size)); static int dbcs_char2cells __ARGS((int c)); + static int dbcs_ptr2cells_len __ARGS((char_u *p, int size)); static int dbcs_ptr2char __ARGS((char_u *p)); /* Lookup table to quickly get the length in bytes of a UTF-8 character from *************** *** 606,614 **** --- 609,619 ---- if (enc_utf8) { mb_ptr2len = utfc_ptr2len; + mb_ptr2len_len = utfc_ptr2len_len; mb_char2len = utf_char2len; mb_char2bytes = utf_char2bytes; mb_ptr2cells = utf_ptr2cells; + mb_ptr2cells_len = utf_ptr2cells_len; mb_char2cells = utf_char2cells; mb_off2cells = utf_off2cells; mb_ptr2char = utf_ptr2char; *************** *** 617,625 **** --- 622,632 ---- else if (enc_dbcs != 0) { mb_ptr2len = dbcs_ptr2len; + mb_ptr2len_len = dbcs_ptr2len_len; mb_char2len = dbcs_char2len; mb_char2bytes = dbcs_char2bytes; mb_ptr2cells = dbcs_ptr2cells; + mb_ptr2cells_len = dbcs_ptr2cells_len; mb_char2cells = dbcs_char2cells; mb_off2cells = dbcs_off2cells; mb_ptr2char = dbcs_ptr2char; *************** *** 628,636 **** --- 635,645 ---- else { mb_ptr2len = latin_ptr2len; + mb_ptr2len_len = latin_ptr2len_len; mb_char2len = latin_char2len; mb_char2bytes = latin_char2bytes; mb_ptr2cells = latin_ptr2cells; + mb_ptr2cells_len = latin_ptr2cells_len; mb_char2cells = latin_char2cells; mb_off2cells = latin_off2cells; mb_ptr2char = latin_ptr2char; *************** *** 1069,1075 **** * Get byte length of character at "*p" but stop at a NUL. * For UTF-8 this includes following composing characters. * Returns 0 when *p is NUL. - * */ int latin_ptr2len(p) --- 1078,1083 ---- *************** *** 1091,1096 **** --- 1099,1138 ---- return len; } + /* + * mb_ptr2len_len() function pointer. + * Like mb_ptr2len(), but limit to read "size" bytes. + * Returns 0 for an empty string. + * Returns 1 for an illegal char or an incomplete byte sequence. + */ + int + latin_ptr2len_len(p, size) + char_u *p; + int size; + { + if (size < 1 || *p == NUL) + return 0; + return 1; + } + + static int + dbcs_ptr2len_len(p, size) + char_u *p; + int size; + { + int len; + + if (size < 1 || *p == NUL) + return 0; + if (size == 1) + return 1; + /* Check that second byte is not missing. */ + len = MB_BYTE2LEN(*p); + if (len == 2 && p[1] == NUL) + len = 1; + return len; + } + struct interval { unsigned short first; *************** *** 1287,1292 **** --- 1329,1383 ---- } /* + * mb_ptr2cells_len() function pointer. + * Like mb_ptr2cells(), but limit string length to "size". + * For an empty string or truncated character returns 1. + */ + int + latin_ptr2cells_len(p, size) + char_u *p UNUSED; + int size UNUSED; + { + return 1; + } + + static int + utf_ptr2cells_len(p, size) + char_u *p; + int size; + { + int c; + + /* Need to convert to a wide character. */ + if (size > 0 && *p >= 0x80) + { + if (utf_ptr2len_len(p, size) < utf8len_tab[*p]) + return 1; + c = utf_ptr2char(p); + /* An illegal byte is displayed as . */ + if (utf_ptr2len(p) == 1 || c == NUL) + return 4; + /* If the char is ASCII it must be an overlong sequence. */ + if (c < 0x80) + return char2cells(c); + return utf_char2cells(c); + } + return 1; + } + + static int + dbcs_ptr2cells_len(p, size) + char_u *p; + int size; + { + /* Number of cells is equal to number of bytes, except for euc-jp when + * the first byte is 0x8e. */ + if (size <= 1 || (enc_dbcs == DBCS_JPNU && *p == 0x8e)) + return 1; + return MB_BYTE2LEN(*p); + } + + /* * mb_char2cells() function pointer. * Return the number of display cells character "c" occupies. * Only takes care of multi-byte chars, not "^C" and such. *************** *** 1716,1721 **** --- 1807,1813 ---- /* * Return the number of bytes the UTF-8 encoding of the character at "p[size]" * takes. This includes following composing characters. + * Returns 0 for an empty string. * Returns 1 for an illegal char or an incomplete byte sequence. */ int *************** *** 1728,1734 **** int prevlen; #endif ! if (*p == NUL) return 0; if (p[0] < 0x80 && (size == 1 || p[1] < 0x80)) /* be quick for ASCII */ return 1; --- 1820,1826 ---- int prevlen; #endif ! if (size < 1 || *p == NUL) return 0; if (p[0] < 0x80 && (size == 1 || p[1] < 0x80)) /* be quick for ASCII */ return 1; *** ../vim-7.2.199/src/proto/mbyte.pro 2008-07-13 19:34:19.000000000 +0200 --- src/proto/mbyte.pro 2009-06-16 14:58:39.000000000 +0200 *************** *** 7,16 **** --- 7,18 ---- int latin_char2len __ARGS((int c)); int latin_char2bytes __ARGS((int c, char_u *buf)); int latin_ptr2len __ARGS((char_u *p)); + int latin_ptr2len_len __ARGS((char_u *p, int size)); int utf_char2cells __ARGS((int c)); int latin_ptr2cells __ARGS((char_u *p)); int utf_ptr2cells __ARGS((char_u *p)); int dbcs_ptr2cells __ARGS((char_u *p)); + int latin_ptr2cells_len __ARGS((char_u *p, int size)); int latin_char2cells __ARGS((int c)); int latin_off2cells __ARGS((unsigned off, unsigned max_off)); int dbcs_off2cells __ARGS((unsigned off, unsigned max_off)); *************** *** 85,90 **** --- 87,93 ---- int preedit_get_status __ARGS((void)); int im_is_preediting __ARGS((void)); int convert_setup __ARGS((vimconv_T *vcp, char_u *from, char_u *to)); + int convert_setup_ext __ARGS((vimconv_T *vcp, char_u *from, int from_unicode_is_utf8, char_u *to, int to_unicode_is_utf8)); int convert_input __ARGS((char_u *ptr, int len, int maxlen)); int convert_input_safe __ARGS((char_u *ptr, int len, int maxlen, char_u **restp, int *restlenp)); char_u *string_convert __ARGS((vimconv_T *vcp, char_u *ptr, int *lenp)); *** ../vim-7.2.199/src/version.c 2009-06-16 14:31:56.000000000 +0200 --- src/version.c 2009-06-16 14:37:38.000000000 +0200 *************** *** 678,679 **** --- 678,681 ---- { /* Add new patch number below this line */ + /**/ + 200, /**/ -- How To Keep A Healthy Level Of Insanity: 12. Sing along at the opera. /// 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 ///