CVE-2023-0051 (published 2023-01-04T18:15Z)

Heap-based Buffer Overflow in GitHub repository vim/vim prior to 9.0.1144.

CVSS v3 base score: 7.8, HIGH (CVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H)

Weakness information:
cwe_id: CWE-122
cwe_name: Heap-based Buffer Overflow
description: A heap overflow condition is a buffer overflow, where the buffer that can be overwritten is allocated in the heap portion of memory, generally meaning that the buffer was allocated using a routine such as malloc().
extended_description: 
            
            
         
         

Fix information:
repo_url: https://github.com/vim/vim
commit_details: repo_url: https://github.com/vim/vim
author: Bram Moolenaar
author_date: 2023-01-04 15:56:51+00:00
msg: patch 9.0.1144: reading beyond text

Problem:    Reading beyond text.
Solution:   Add strlen_maxlen() and use it.
repository: repo_url: https://github.com/vim/vim
repo_name: vim/vim
description: The official Vim repository
repo_language: Vim Script
owner: vim
file_changes: filename: message.c
change_type: ModificationType.MODIFY
diff: @@ -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;

programming_language: C
filename: strings.pro
change_type: ModificationType.MODIFY
diff: @@ -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);

programming_language: C
filename: strings.c
change_type: ModificationType.MODIFY
diff: @@ -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;

programming_language: C
filename: test_cmdline.vim
change_type: ModificationType.MODIFY
diff: @@ -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

programming_language: Lua
filename: version.c
change_type: ModificationType.MODIFY
diff: @@ -695,6 +695,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    1144,
 /**/
     1143,
 /**/

programming_language: Ruby