# HG changeset patch # User Bram Moolenaar # Date 1672848005 -3600 # Node ID d605a50e7623fbdb486ae3df8b772f3a2a6213d9 # Parent f061953e161874ee4fe7678d5795bc269881a814 patch 9.0.1144: reading beyond text Commit: https://github.com/vim/vim/commit/c32949b0779106ed5710ae3bffc5053e49083ab4 Author: Bram Moolenaar Date: Wed Jan 4 15:56:51 2023 +0000 patch 9.0.1144: reading beyond text Problem: Reading beyond text. Solution: Add strlen_maxlen() and use it. diff --git a/src/message.c b/src/message.c --- a/src/message.c +++ b/src/message.c @@ -3055,7 +3055,8 @@ msg_puts_printf(char_u *str, int maxlen) { char_u *tofree = NULL; - if (maxlen > 0 && STRLEN(p) > (size_t)maxlen) + if (maxlen > 0 && vim_strlen_maxlen((char *)p, (size_t)maxlen) + >= (size_t)maxlen) { tofree = vim_strnsave(p, (size_t)maxlen); p = tofree; diff --git a/src/proto/strings.pro b/src/proto/strings.pro --- a/src/proto/strings.pro +++ b/src/proto/strings.pro @@ -12,6 +12,7 @@ char_u *strlow_save(char_u *orig); void del_trailing_spaces(char_u *ptr); void vim_strncpy(char_u *to, char_u *from, size_t len); void vim_strcat(char_u *to, char_u *from, size_t tosize); +size_t vim_strlen_maxlen(char *s, size_t maxlen); int vim_stricmp(char *s1, char *s2); int vim_strnicmp(char *s1, char *s2, size_t len); char_u *vim_strchr(char_u *string, int c); diff --git a/src/strings.c b/src/strings.c --- a/src/strings.c +++ b/src/strings.c @@ -525,6 +525,19 @@ vim_strcat(char_u *to, char_u *from, siz mch_memmove(to + tolen, from, fromlen + 1); } +/* + * A version of strlen() that has a maximum length. + */ + size_t +vim_strlen_maxlen(char *s, size_t maxlen) +{ + size_t i; + for (i = 0; i < maxlen; ++i) + if (s[i] == NUL) + break; + return i; +} + #if (!defined(HAVE_STRCASECMP) && !defined(HAVE_STRICMP)) || defined(PROTO) /* * Compare two strings, ignoring case, using current locale. @@ -582,7 +595,7 @@ vim_strnicmp(char *s1, char *s2, size_t * 128 to 255 correctly. It also doesn't return a pointer to the NUL at the * end of the string. */ - char_u * + char_u * vim_strchr(char_u *string, int c) { char_u *p; diff --git a/src/testdir/test_cmdline.vim b/src/testdir/test_cmdline.vim --- a/src/testdir/test_cmdline.vim +++ b/src/testdir/test_cmdline.vim @@ -654,6 +654,17 @@ func Test_getcompletion() call assert_fails('call getcompletion("abc", [])', 'E1174:') endfunc +func Test_multibyte_expression() + " This was using uninitialized memory. + let lines =<< trim END + set verbose=6 + norm @=ٷ + qall! + END + call writefile(lines, 'XmultiScript', 'D') + call RunVim('', '', '-u NONE -n -e -s -S XmultiScript') +endfunc + " Test for getcompletion() with "fuzzy" in 'wildoptions' func Test_getcompletion_wildoptions() let save_wildoptions = &wildoptions diff --git a/src/version.c b/src/version.c --- a/src/version.c +++ b/src/version.c @@ -696,6 +696,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 1144, +/**/ 1143, /**/ 1142,