From c32949b0779106ed5710ae3bffc5053e49083ab4 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Wed, 4 Jan 2023 15:56:51 +0000 Subject: [PATCH] patch 9.0.1144: reading beyond text Problem: Reading beyond text. Solution: Add strlen_maxlen() and use it. --- src/message.c | 3 ++- src/proto/strings.pro | 1 + src/strings.c | 15 ++++++++++++++- src/testdir/test_cmdline.vim | 11 +++++++++++ src/version.c | 2 ++ 5 files changed, 30 insertions(+), 2 deletions(-) diff --git a/src/message.c b/src/message.c index 591691f3f6567..bb3517c94ed86 100644 --- 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 index 50bbf29fe8574..60220883156a1 100644 --- 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 index edcae6f8a49e7..9174265997eeb 100644 --- a/src/strings.c +++ b/src/strings.c @@ -525,6 +525,19 @@ vim_strcat(char_u *to, char_u *from, size_t tosize) 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 len) * 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 index 78f9ba22bfb6e..91ff6f1567f4e 100644 --- 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 index 4ccbd537abe30..6e652c697cffc 100644 --- a/src/version.c +++ b/src/version.c @@ -695,6 +695,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1144, /**/ 1143, /**/