Package: release.debian.org
Severity: normal
Tags: bookworm
User: release.debian....@packages.debian.org
Usertags: pu
X-Debbugs-Cc: v...@packages.debian.org
Control: affects -1 + src:vim

Fixes for eight CVEs, backported from upstream, all already in sid.
Tested with Vim's existing extensive test suite, and some of the fixes add new
tests, too.  Everything passes.

These are all simple CVEs caused by the usual suspect C programming issues, so
there is no expected negative impact on users.

I have already uploaded.  Thanks!

-- 
Sean Whitton
diff -Nru vim-9.0.1378/debian/changelog vim-9.0.1378/debian/changelog
--- vim-9.0.1378/debian/changelog       2023-05-04 11:24:44.000000000 +0100
+++ vim-9.0.1378/debian/changelog       2025-01-23 13:00:20.000000000 +0000
@@ -1,3 +1,21 @@
+vim (2:9.0.1378-2+deb12u1) bookworm; urgency=high
+
+  * Backport security fixes:
+    - 9.0.1532: Crash when expanding "~" in substitute
+      (Closes: #1035955, CVE-2023-2610)
+    - 9.0.1848: buffer-overflow in vim_regsub_both() (CVE-2023-4738)
+    - 9.0.1858: heap use after free in ins_compl_get_exp() (CVE-2023-4752)
+    - 9.0.1873: heap-buffer-overflow in vim_regsub_both (CVE-2023-4781)
+    - 9.0.1969: buffer-overflow in trunc_string()
+      (Closes: #1053694, CVE-2023-5344)
+    - 9.0.2142: stack-buffer-overflow in option callback functions
+      (CVE-2024-22667)
+    - 9.1.0697: heap-buffer-overflow in ins_typebuf (CVE-2024-43802)
+    - 9.1.0764: use-after-free when closing a buffer
+      (Closes: #1084806, CVE-2024-47814).
+
+ -- Sean Whitton <spwhit...@spwhitton.name>  Thu, 23 Jan 2025 13:00:20 +0000
+
 vim (2:9.0.1378-2) unstable; urgency=medium
 
   * Backport 9.0.1499 to fix CVE-2023-2426 (Closes: #1035323)
diff -Nru vim-9.0.1378/debian/patches/CVE-2023-2610.patch 
vim-9.0.1378/debian/patches/CVE-2023-2610.patch
--- vim-9.0.1378/debian/patches/CVE-2023-2610.patch     1970-01-01 
01:00:00.000000000 +0100
+++ vim-9.0.1378/debian/patches/CVE-2023-2610.patch     2025-01-23 
13:00:20.000000000 +0000
@@ -0,0 +1,111 @@
+From: Bram Moolenaar <b...@vim.org>
+Date: Tue, 9 May 2023 21:15:30 +0100
+Subject: patch 9.0.1532: crash when expanding "~" in substitute causes very
+ long text
+
+Problem:    Crash when expanding "~" in substitute causes very long text.
+Solution:   Limit the text length to MAXCOL.
+(cherry picked from commit ab9a2d884b3a4abe319606ea95a5a6d6b01cd73a)
+---
+ src/regexp.c                    | 30 +++++++++++++++++++-----------
+ src/testdir/test_substitute.vim | 14 ++++++++++++++
+ src/version.c                   |  2 ++
+ 3 files changed, 35 insertions(+), 11 deletions(-)
+
+diff --git a/src/regexp.c b/src/regexp.c
+index f18f33d..08a7cdd 100644
+--- a/src/regexp.c
++++ b/src/regexp.c
+@@ -1767,10 +1767,7 @@ do_Lower(int *d, int c)
+ regtilde(char_u *source, int magic)
+ {
+     char_u    *newsub = source;
+-    char_u    *tmpsub;
+     char_u    *p;
+-    int               len;
+-    int               prevlen;
+ 
+     for (p = newsub; *p; ++p)
+     {
+@@ -1779,24 +1776,35 @@ regtilde(char_u *source, int magic)
+           if (reg_prev_sub != NULL)
+           {
+               // length = len(newsub) - 1 + len(prev_sub) + 1
+-              prevlen = (int)STRLEN(reg_prev_sub);
+-              tmpsub = alloc(STRLEN(newsub) + prevlen);
++              // Avoid making the text longer than MAXCOL, it will cause
++              // trouble at some point.
++              size_t  prevsublen = STRLEN(reg_prev_sub);
++              size_t  newsublen = STRLEN(newsub);
++              if (prevsublen > MAXCOL || newsublen > MAXCOL
++                                          || newsublen + prevsublen > MAXCOL)
++              {
++                  emsg(_(e_resulting_text_too_long));
++                  break;
++              }
++
++              char_u *tmpsub = alloc(newsublen + prevsublen);
+               if (tmpsub != NULL)
+               {
+                   // copy prefix
+-                  len = (int)(p - newsub);    // not including ~
+-                  mch_memmove(tmpsub, newsub, (size_t)len);
++                  size_t prefixlen = p - newsub;      // not including ~
++                  mch_memmove(tmpsub, newsub, prefixlen);
+                   // interpret tilde
+-                  mch_memmove(tmpsub + len, reg_prev_sub, (size_t)prevlen);
++                  mch_memmove(tmpsub + prefixlen, reg_prev_sub,
++                                                             prevsublen);
+                   // copy postfix
+                   if (!magic)
+                       ++p;                    // back off backslash
+-                  STRCPY(tmpsub + len + prevlen, p + 1);
++                  STRCPY(tmpsub + prefixlen + prevsublen, p + 1);
+ 
+-                  if (newsub != source)       // already allocated newsub
++                  if (newsub != source)       // allocated newsub before
+                       vim_free(newsub);
+                   newsub = tmpsub;
+-                  p = newsub + len + prevlen;
++                  p = newsub + prefixlen + prevsublen;
+               }
+           }
+           else if (magic)
+diff --git a/src/testdir/test_substitute.vim b/src/testdir/test_substitute.vim
+index 7491b61..32e2f27 100644
+--- a/src/testdir/test_substitute.vim
++++ b/src/testdir/test_substitute.vim
+@@ -1414,6 +1414,20 @@ func Test_substitute_short_cmd()
+   bw!
+ endfunc
+ 
++" Check handling expanding "~" resulting in extremely long text.
++func Test_substitute_tilde_too_long()
++  enew!
++
++  s/.*/ixxx
++  s//~~~~~~~~~AAAAAAA@(
++
++  " Either fails with "out of memory" or "text too long".
++  " This can take a long time.
++  call assert_fails('sil! norm &&&&&&&&&', ['E1240:\|E342:'])
++
++  bwipe!
++endfunc
++
+ " This should be done last to reveal a memory leak when vim_regsub_both() is
+ " called to evaluate an expression but it is not used in a second call.
+ func Test_z_substitute_expr_leak()
+diff --git a/src/version.c b/src/version.c
+index 0e83a6f..63e2a41 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 */
++/**/
++    1532,
+ /**/
+     1499,
+ /**/
diff -Nru vim-9.0.1378/debian/patches/CVE-2023-4738.patch 
vim-9.0.1378/debian/patches/CVE-2023-4738.patch
--- vim-9.0.1378/debian/patches/CVE-2023-4738.patch     1970-01-01 
01:00:00.000000000 +0100
+++ vim-9.0.1378/debian/patches/CVE-2023-4738.patch     2025-01-23 
13:00:20.000000000 +0000
@@ -0,0 +1,74 @@
+From: Christian Brabandt <c...@256bit.org>
+Date: Sat, 2 Sep 2023 21:15:52 +0200
+Subject: patch 9.0.1848: [security] buffer-overflow in vim_regsub_both()
+
+Problem:  buffer-overflow in vim_regsub_both()
+Solution: Check remaining space
+
+Signed-off-by: Christian Brabandt <c...@256bit.org>
+(cherry picked from commit ced2c7394aafdc90fb7845e09b3a3fee23d48cb1)
+---
+ src/ex_cmds.c                     |  3 +++
+ src/regexp.c                      |  3 ++-
+ src/testdir/crash/vim_regsub_both | 10 ++++++++++
+ src/version.c                     |  2 ++
+ 4 files changed, 17 insertions(+), 1 deletion(-)
+ create mode 100644 src/testdir/crash/vim_regsub_both
+
+diff --git a/src/ex_cmds.c b/src/ex_cmds.c
+index 0d83980..62d7b9c 100644
+--- a/src/ex_cmds.c
++++ b/src/ex_cmds.c
+@@ -4641,6 +4641,9 @@ ex_substitute(exarg_T *eap)
+               mch_memmove(new_end, sub_firstline + copycol, (size_t)copy_len);
+               new_end += copy_len;
+ 
++              if (new_start_len - copy_len < sublen)
++                  sublen = new_start_len - copy_len - 1;
++
+ #ifdef FEAT_EVAL
+               ++textlock;
+ #endif
+diff --git a/src/regexp.c b/src/regexp.c
+index 08a7cdd..a6ec2a9 100644
+--- a/src/regexp.c
++++ b/src/regexp.c
+@@ -2051,7 +2051,8 @@ vim_regsub_both(
+       // "flags & REGSUB_COPY" != 0.
+       if (copy)
+       {
+-          if (eval_result[nested] != NULL)
++          if (eval_result[nested] != NULL &&
++                  STRLEN(eval_result[nested]) < destlen)
+           {
+               STRCPY(dest, eval_result[nested]);
+               dst += STRLEN(eval_result[nested]);
+diff --git a/src/testdir/crash/vim_regsub_both 
b/src/testdir/crash/vim_regsub_both
+new file mode 100644
+index 0000000..a82b205
+--- /dev/null
++++ b/src/testdir/crash/vim_regsub_both
+@@ -0,0 +1,10 @@
++fu R()
++sil!norm0z=
++endf
++cal R()
++s/\%')/\=R()
++d
++no0 normyynore sm:vs0@vvvvvvvvvvse()dir(�Xtest=csd{so88
++vs
++0scr
++so
+diff --git a/src/version.c b/src/version.c
+index 63e2a41..244264c 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 */
++/**/
++    1848,
+ /**/
+     1532,
+ /**/
diff -Nru vim-9.0.1378/debian/patches/CVE-2023-4752.patch 
vim-9.0.1378/debian/patches/CVE-2023-4752.patch
--- vim-9.0.1378/debian/patches/CVE-2023-4752.patch     1970-01-01 
01:00:00.000000000 +0100
+++ vim-9.0.1378/debian/patches/CVE-2023-4752.patch     2025-01-23 
13:00:20.000000000 +0000
@@ -0,0 +1,55 @@
+From: Christian Brabandt <c...@256bit.org>
+Date: Sun, 3 Sep 2023 21:24:33 +0200
+Subject: patch 9.0.1858: [security] heap use after free in
+ ins_compl_get_exp()
+
+Problem:  heap use after free in ins_compl_get_exp()
+Solution: validate buffer before accessing it
+
+Signed-off-by: Christian Brabandt <c...@256bit.org>
+(cherry picked from commit ee9166eb3b41846661a39b662dc7ebe8b5e15139)
+---
+ src/insexpand.c                   | 2 +-
+ src/testdir/crash/poc_tagfunc.vim | 6 ++++++
+ src/version.c                     | 2 ++
+ 3 files changed, 9 insertions(+), 1 deletion(-)
+ create mode 100644 src/testdir/crash/poc_tagfunc.vim
+
+diff --git a/src/insexpand.c b/src/insexpand.c
+index 2737f2b..acd0a3b 100644
+--- a/src/insexpand.c
++++ b/src/insexpand.c
+@@ -3851,7 +3851,7 @@ ins_compl_get_exp(pos_T *ini)
+       else
+       {
+           // Mark a buffer scanned when it has been scanned completely
+-          if (type == 0 || type == CTRL_X_PATH_PATTERNS)
++          if (buf_valid(st.ins_buf) && (type == 0 || type == 
CTRL_X_PATH_PATTERNS))
+               st.ins_buf->b_scanned = TRUE;
+ 
+           compl_started = FALSE;
+diff --git a/src/testdir/crash/poc_tagfunc.vim 
b/src/testdir/crash/poc_tagfunc.vim
+new file mode 100644
+index 0000000..49d9b6f
+--- /dev/null
++++ b/src/testdir/crash/poc_tagfunc.vim
+@@ -0,0 +1,6 @@
++fu Tagfunc(t,f,o)
++  bw
++endf
++set tagfunc=Tagfunc
++n0
++sil0norm0i
+diff --git a/src/version.c b/src/version.c
+index 244264c..49a8d6b 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 */
++/**/
++    1858,
+ /**/
+     1848,
+ /**/
Binary files /tmp/h5HGhcbA1O/vim-9.0.1378/debian/patches/CVE-2023-4781.patch 
and /tmp/QlEbjXFHGR/vim-9.0.1378/debian/patches/CVE-2023-4781.patch differ
diff -Nru vim-9.0.1378/debian/patches/CVE-2023-5344.patch 
vim-9.0.1378/debian/patches/CVE-2023-5344.patch
--- vim-9.0.1378/debian/patches/CVE-2023-5344.patch     1970-01-01 
01:00:00.000000000 +0100
+++ vim-9.0.1378/debian/patches/CVE-2023-5344.patch     2025-01-23 
13:00:20.000000000 +0000
@@ -0,0 +1,58 @@
+From: Christian Brabandt <c...@256bit.org>
+Date: Mon, 2 Oct 2023 20:59:08 +0200
+Subject: patch 9.0.1969: [security] buffer-overflow in trunc_string()
+
+Problem:  buffer-overflow in trunc_string()
+Solution: Add NULL at end of buffer
+
+Currently trunc_string() assumes that when the string is too long,
+buf[e-1] will always be writeable. But that assumption may not always be
+true. The condition currently looks like this
+
+    else if (e + 3 < buflen)
+    [...]
+    else
+    {
+       // can't fit in the "...", just truncate it
+       buf[e - 1] = NUL;
+    }
+
+but this means, we may run into the last else clause with e still being
+larger than buflen. So a buffer overflow occurs.
+
+So instead of using `buf[e - 1]`, let's just always
+truncate at `buf[buflen - 1]` which should always be writable.
+
+Signed-off-by: Christian Brabandt <c...@256bit.org>
+(cherry picked from commit 3bd7fa12e146c6051490d048a4acbfba974eeb04)
+---
+ src/message.c | 2 +-
+ src/version.c | 2 ++
+ 2 files changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/src/message.c b/src/message.c
+index 18f3013..c47f819 100644
+--- a/src/message.c
++++ b/src/message.c
+@@ -353,7 +353,7 @@ trunc_string(
+     else
+     {
+       // can't fit in the "...", just truncate it
+-      buf[e - 1] = NUL;
++      buf[buflen - 1] = NUL;
+     }
+ }
+ 
+diff --git a/src/version.c b/src/version.c
+index 8feb0c4..9071b1a 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 */
++/**/
++    1969,
+ /**/
+     1873,
+ /**/
diff -Nru vim-9.0.1378/debian/patches/CVE-2024-22667.patch 
vim-9.0.1378/debian/patches/CVE-2024-22667.patch
--- vim-9.0.1378/debian/patches/CVE-2024-22667.patch    1970-01-01 
01:00:00.000000000 +0100
+++ vim-9.0.1378/debian/patches/CVE-2024-22667.patch    2025-01-23 
13:00:20.000000000 +0000
@@ -0,0 +1,392 @@
+From: Christian Brabandt <c...@256bit.org>
+Date: Wed, 29 Nov 2023 11:34:05 +0100
+Subject: patch 9.0.2142: [security]: stack-buffer-overflow in option callback
+ functions
+
+Problem:  [security]: stack-buffer-overflow in option callback functions
+Solution: pass size of errbuf down the call stack, use snprintf()
+          instead of sprintf()
+
+We pass the error buffer down to the option callback functions, but in
+some parts of the code, we simply use sprintf(buf) to write into the error
+buffer, which can overflow.
+
+So let's pass down the length of the error buffer and use sprintf(buf, size)
+instead.
+
+Reported by @henices, thanks!
+
+Signed-off-by: Christian Brabandt <c...@256bit.org>
+(cherry picked from commit b39b240c386a5a29241415541f1c99e2e6b8ce47)
+---
+ src/map.c                             |  2 +-
+ src/option.c                          | 14 +++++----
+ src/option.h                          |  2 ++
+ src/optionstr.c                       | 59 ++++++++++++++++++++++-------------
+ src/proto/optionstr.pro               |  4 +--
+ src/structs.h                         |  2 ++
+ src/testdir/crash/poc_did_set_langmap |  1 +
+ src/version.c                         |  2 ++
+ 8 files changed, 55 insertions(+), 31 deletions(-)
+ create mode 100644 src/testdir/crash/poc_did_set_langmap
+
+diff --git a/src/map.c b/src/map.c
+index 7c95286..5d88005 100644
+--- a/src/map.c
++++ b/src/map.c
+@@ -3111,7 +3111,7 @@ did_set_langmap(optset_T *args UNUSED)
+                   {
+                       if (p[0] != ',')
+                       {
+-                          sprintf(args->os_errbuf,
++                          snprintf(args->os_errbuf, args->os_errbuflen,
+                                   
_(e_langmap_extra_characters_after_semicolon_str),
+                                   p);
+                           return args->os_errbuf;
+diff --git a/src/option.c b/src/option.c
+index 1203180..ea94845 100644
+--- a/src/option.c
++++ b/src/option.c
+@@ -1923,6 +1923,7 @@ do_set_option_string(
+       int         cp_val,
+       char_u      *varp_arg,
+       char        *errbuf,
++      int         errbuflen,
+       int         *value_checked,
+       char        **errmsg)
+ {
+@@ -2021,7 +2022,7 @@ do_set_option_string(
+       // be triggered that can cause havoc.
+       *errmsg = did_set_string_option(
+                       opt_idx, (char_u **)varp, oldval, newval, errbuf,
+-                      opt_flags, value_checked);
++                      errbuflen, opt_flags, value_checked);
+ 
+       secure = secure_saved;
+     }
+@@ -2274,7 +2275,7 @@ do_set_option_value(
+       {
+           // string option
+           if (do_set_option_string(opt_idx, opt_flags, &arg, nextchar, op,
+-                                      flags, cp_val, varp, errbuf,
++                                      flags, cp_val, varp, errbuf, errbuflen,
+                                       &value_checked, &errmsg) == FAIL)
+           {
+               if (errmsg != NULL)
+@@ -2566,12 +2567,12 @@ do_set(
+       {
+           int         stopopteval = FALSE;
+           char        *errmsg = NULL;
+-          char        errbuf[80];
++          char        errbuf[ERR_BUFLEN];
+           char_u      *startarg = arg;
+ 
+           errmsg = do_set_option(opt_flags, &arg, arg_start, &startarg,
+                                       &did_show, &stopopteval, errbuf,
+-                                      sizeof(errbuf));
++                                      ERR_BUFLEN);
+           if (stopopteval)
+               break;
+ 
+@@ -5154,7 +5155,8 @@ set_option_value(
+     int               opt_idx;
+     char_u    *varp;
+     long_u    flags;
+-    static char       errbuf[80];
++    static char       errbuf[ERR_BUFLEN];
++    int               errbuflen = ERR_BUFLEN;
+ 
+     opt_idx = findoption(name);
+     if (opt_idx < 0)
+@@ -5197,7 +5199,7 @@ set_option_value(
+       }
+ #endif
+       if (flags & P_STRING)
+-          return set_string_option(opt_idx, string, opt_flags, errbuf);
++          return set_string_option(opt_idx, string, opt_flags, errbuf, 
errbuflen);
+ 
+       varp = get_varp_scope(&(options[opt_idx]), opt_flags);
+       if (varp != NULL)       // hidden option is not changed
+diff --git a/src/option.h b/src/option.h
+index 487d87c..d5f7f61 100644
+--- a/src/option.h
++++ b/src/option.h
+@@ -1312,4 +1312,6 @@ enum
+ // Value for b_p_ul indicating the global value must be used.
+ #define NO_LOCAL_UNDOLEVEL (-123456)
+ 
++#define ERR_BUFLEN 80
++
+ #endif // _OPTION_H_
+diff --git a/src/optionstr.c b/src/optionstr.c
+index aff8b61..eac89fe 100644
+--- a/src/optionstr.c
++++ b/src/optionstr.c
+@@ -196,11 +196,12 @@ trigger_optionset_string(
+ #endif
+ 
+     static char *
+-illegal_char(char *errbuf, int c)
++illegal_char(char *errbuf, int errbuflen, int c)
+ {
+     if (errbuf == NULL)
+       return "";
+-    sprintf((char *)errbuf, _(e_illegal_character_str), (char *)transchar(c));
++    snprintf((char *)errbuf, errbuflen, _(e_illegal_character_str),
++                  (char *)transchar(c));
+     return errbuf;
+ }
+ 
+@@ -489,7 +490,8 @@ set_string_option(
+     int               opt_idx,
+     char_u    *value,
+     int               opt_flags,      // OPT_LOCAL and/or OPT_GLOBAL
+-    char      *errbuf)
++    char      *errbuf,
++    int               errbuflen)
+ {
+     char_u    *s;
+     char_u    **varp;
+@@ -543,7 +545,7 @@ set_string_option(
+     }
+ #endif
+     if ((errmsg = did_set_string_option(opt_idx, varp, oldval, value, errbuf,
+-                  opt_flags, &value_checked)) == NULL)
++                  errbuflen, opt_flags, &value_checked)) == NULL)
+       did_set_option(opt_idx, opt_flags, TRUE, value_checked);
+ 
+ #if defined(FEAT_EVAL)
+@@ -579,7 +581,8 @@ valid_filetype(char_u *val)
+ check_stl_option(char_u *s)
+ {
+     int               groupdepth = 0;
+-    static char errbuf[80];
++    static char errbuf[ERR_BUFLEN];
++    int               errbuflen = ERR_BUFLEN;
+ 
+     while (*s)
+     {
+@@ -620,7 +623,7 @@ check_stl_option(char_u *s)
+       }
+       if (vim_strchr(STL_ALL, *s) == NULL)
+       {
+-          return illegal_char(errbuf, *s);
++          return illegal_char(errbuf, errbuflen, *s);
+       }
+       if (*s == '{')
+       {
+@@ -628,7 +631,7 @@ check_stl_option(char_u *s)
+ 
+           if (reevaluate && *++s == '}')
+               // "}" is not allowed immediately after "%{%"
+-              return illegal_char(errbuf, '}');
++              return illegal_char(errbuf, errbuflen, '}');
+           while ((*s != '}' || (reevaluate && s[-1] != '%')) && *s)
+               s++;
+           if (*s != '}')
+@@ -683,13 +686,17 @@ did_set_opt_strings(char_u *val, char **values, int list)
+  * An option which is a list of flags is set.  Valid values are in 'flags'.
+  */
+     static char *
+-did_set_option_listflag(char_u *val, char_u *flags, char *errbuf)
++did_set_option_listflag(
++      char_u *val,
++      char_u *flags,
++      char *errbuf,
++      int errbuflen)
+ {
+     char_u    *s;
+ 
+     for (s = val; *s; ++s)
+       if (vim_strchr(flags, *s) == NULL)
+-          return illegal_char(errbuf, *s);
++          return illegal_char(errbuf, errbuflen, *s);
+ 
+     return NULL;
+ }
+@@ -1001,7 +1008,7 @@ did_set_comments(optset_T *args)
+           if (vim_strchr((char_u *)COM_ALL, *s) == NULL
+                   && !VIM_ISDIGIT(*s) && *s != '-')
+           {
+-              errmsg = illegal_char(args->os_errbuf, *s);
++              errmsg = illegal_char(args->os_errbuf, args->os_errbuflen, *s);
+               break;
+           }
+           ++s;
+@@ -1057,7 +1064,7 @@ did_set_complete(optset_T *args)
+       if (!*s)
+           break;
+       if (vim_strchr((char_u *)".wbuksid]tU", *s) == NULL)
+-          return illegal_char(args->os_errbuf, *s);
++          return illegal_char(args->os_errbuf, args->os_errbuflen, *s);
+       if (*++s != NUL && *s != ',' && *s != ' ')
+       {
+           if (s[-1] == 'k' || s[-1] == 's')
+@@ -1074,7 +1081,7 @@ did_set_complete(optset_T *args)
+           {
+               if (args->os_errbuf != NULL)
+               {
+-                  sprintf((char *)args->os_errbuf,
++                  snprintf((char *)args->os_errbuf, args->os_errbuflen,
+                           _(e_illegal_character_after_chr), *--s);
+                   return args->os_errbuf;
+               }
+@@ -1138,7 +1145,8 @@ did_set_concealcursor(optset_T *args)
+ {
+     char_u    **varp = (char_u **)args->os_varp;
+ 
+-    return did_set_option_listflag(*varp, (char_u *)COCU_ALL, 
args->os_errbuf);
++    return did_set_option_listflag(*varp, (char_u *)COCU_ALL, args->os_errbuf,
++                  args->os_errbuflen);
+ }
+ #endif
+ 
+@@ -1150,7 +1158,8 @@ did_set_cpoptions(optset_T *args)
+ {
+     char_u    **varp = (char_u **)args->os_varp;
+ 
+-    return did_set_option_listflag(*varp, (char_u *)CPO_ALL, args->os_errbuf);
++    return did_set_option_listflag(*varp, (char_u *)CPO_ALL, args->os_errbuf,
++                  args->os_errbuflen);
+ }
+ 
+ #if defined(FEAT_CRYPT) || defined(PROTO)
+@@ -1592,7 +1601,8 @@ did_set_formatoptions(optset_T *args)
+ {
+     char_u    **varp = (char_u **)args->os_varp;
+ 
+-    return did_set_option_listflag(*varp, (char_u *)FO_ALL, args->os_errbuf);
++    return did_set_option_listflag(*varp, (char_u *)FO_ALL, args->os_errbuf,
++                  args->os_errbuflen);
+ }
+ 
+ #if defined(CURSOR_SHAPE) || defined(PROTO)
+@@ -1706,7 +1716,8 @@ did_set_guioptions(optset_T *args)
+     char_u    **varp = (char_u **)args->os_varp;
+     char *errmsg;
+ 
+-    errmsg = did_set_option_listflag(*varp, (char_u *)GO_ALL, 
args->os_errbuf);
++    errmsg = did_set_option_listflag(*varp, (char_u *)GO_ALL, args->os_errbuf,
++                  args->os_errbuflen);
+     if (errmsg != NULL)
+       return errmsg;
+ 
+@@ -2013,8 +2024,8 @@ did_set_mouse(optset_T *args)
+ {
+     char_u    **varp = (char_u **)args->os_varp;
+ 
+-    return did_set_option_listflag(*varp, (char_u *)MOUSE_ALL,
+-                                                      args->os_errbuf);
++    return did_set_option_listflag(*varp, (char_u *)MOUSE_ALL, 
args->os_errbuf,
++                  args->os_errbuflen);
+ }
+ 
+ /*
+@@ -2292,7 +2303,8 @@ did_set_shortmess(optset_T *args)
+ {
+     char_u    **varp = (char_u **)args->os_varp;
+ 
+-    return did_set_option_listflag(*varp, (char_u *)SHM_ALL, args->os_errbuf);
++    return did_set_option_listflag(*varp, (char_u *)SHM_ALL, args->os_errbuf,
++                  args->os_errbuflen);
+ }
+ 
+ #if defined(FEAT_LINEBREAK) || defined(PROTO)
+@@ -2842,7 +2854,7 @@ did_set_viminfo(optset_T *args)
+       // Check it's a valid character
+       if (vim_strchr((char_u *)"!\"%'/:<@cfhnrs", *s) == NULL)
+       {
+-          errmsg = illegal_char(args->os_errbuf, *s);
++          errmsg = illegal_char(args->os_errbuf, args->os_errbuflen, *s);
+           break;
+       }
+       if (*s == 'n')  // name is always last one
+@@ -2869,7 +2881,7 @@ did_set_viminfo(optset_T *args)
+           {
+               if (args->os_errbuf != NULL)
+               {
+-                  sprintf(args->os_errbuf,
++                  snprintf(args->os_errbuf, args->os_errbuflen,
+                           _(e_missing_number_after_angle_str_angle),
+                           transchar_byte(*(s - 1)));
+                   errmsg = args->os_errbuf;
+@@ -2939,7 +2951,8 @@ did_set_whichwrap(optset_T *args)
+ {
+     char_u    **varp = (char_u **)args->os_varp;
+ 
+-    return did_set_option_listflag(*varp, (char_u *)WW_ALL, args->os_errbuf);
++    return did_set_option_listflag(*varp, (char_u *)WW_ALL,
++                  args->os_errbuf, args->os_errbuflen);
+ }
+ 
+ /*
+@@ -3092,6 +3105,7 @@ did_set_string_option(
+     char_u    *oldval,                // previous value of the option
+     char_u    *value,                 // new value of the option
+     char      *errbuf,                // buffer for errors, or NULL
++    int               errbuflen,              // length of error buffer
+     int               opt_flags,              // OPT_LOCAL and/or OPT_GLOBAL
+     int               *value_checked)         // value was checked to be 
safe, no
+                                       // need to set P_INSECURE
+@@ -3126,6 +3140,7 @@ did_set_string_option(
+       args.os_oldval.string = oldval;
+       args.os_newval.string = value;
+       args.os_errbuf = errbuf;
++      args.os_errbuflen = errbuflen;
+       // Invoke the option specific callback function to validate and apply
+       // the new option value.
+       errmsg = did_set_cb(&args);
+diff --git a/src/proto/optionstr.pro b/src/proto/optionstr.pro
+index 43f285a..1212b11 100644
+--- a/src/proto/optionstr.pro
++++ b/src/proto/optionstr.pro
+@@ -8,7 +8,7 @@ void check_string_option(char_u **pp);
+ void set_string_option_direct(char_u *name, int opt_idx, char_u *val, int 
opt_flags, int set_sid);
+ void set_string_option_direct_in_win(win_T *wp, char_u *name, int opt_idx, 
char_u *val, int opt_flags, int set_sid);
+ void set_string_option_direct_in_buf(buf_T *buf, char_u *name, int opt_idx, 
char_u *val, int opt_flags, int set_sid);
+-char *set_string_option(int opt_idx, char_u *value, int opt_flags, char 
*errbuf);
++char *set_string_option(int opt_idx, char_u *value, int opt_flags, char 
*errbuf, int errbuflen);
+ char *did_set_ambiwidth(optset_T *args);
+ char *did_set_background(optset_T *args);
+ char *did_set_backspace(optset_T *args);
+@@ -119,7 +119,7 @@ char *did_set_wildmode(optset_T *args);
+ char *did_set_wildoptions(optset_T *args);
+ char *did_set_winaltkeys(optset_T *args);
+ char *did_set_wincolor(optset_T *args);
+-char *did_set_string_option(int opt_idx, char_u **varp, char_u *oldval, 
char_u *value, char *errbuf, int opt_flags, int *value_checked);
++char *did_set_string_option(int opt_idx, char_u **varp, char_u *oldval, 
char_u *value, char *errbuf, int errbuflen, int opt_flags, int *value_checked);
+ int check_ff_value(char_u *p);
+ void save_clear_shm_value(void);
+ void restore_shm_value(void);
+diff --git a/src/structs.h b/src/structs.h
+index ac661a6..c220816 100644
+--- a/src/structs.h
++++ b/src/structs.h
+@@ -4846,4 +4846,6 @@ typedef struct
+     // is parameterized, then the "os_errbuf" buffer is used to store the 
error
+     // message (when it is not NULL).
+     char      *os_errbuf;
++    // length of the error buffer
++    int               os_errbuflen;
+ } optset_T;
+diff --git a/src/testdir/crash/poc_did_set_langmap 
b/src/testdir/crash/poc_did_set_langmap
+new file mode 100644
+index 0000000..f77145b
+--- /dev/null
++++ b/src/testdir/crash/poc_did_set_langmap
+@@ -0,0 +1 @@
++se 
lmap=�x�7sil;drlmap=�x�7sil;drmo:
 pm313"
+\ No newline at end of file
+diff --git a/src/version.c b/src/version.c
+index 9071b1a..1ac41a1 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 */
++/**/
++    2142,
+ /**/
+     1969,
+ /**/
Binary files /tmp/h5HGhcbA1O/vim-9.0.1378/debian/patches/CVE-2024-43802.patch 
and /tmp/QlEbjXFHGR/vim-9.0.1378/debian/patches/CVE-2024-43802.patch differ
diff -Nru vim-9.0.1378/debian/patches/CVE-2024-47814.patch 
vim-9.0.1378/debian/patches/CVE-2024-47814.patch
--- vim-9.0.1378/debian/patches/CVE-2024-47814.patch    1970-01-01 
01:00:00.000000000 +0100
+++ vim-9.0.1378/debian/patches/CVE-2024-47814.patch    2025-01-23 
13:00:20.000000000 +0000
@@ -0,0 +1,70 @@
+From: Christian Brabandt <c...@256bit.org>
+Date: Sun, 6 Oct 2024 17:31:10 +0200
+Subject: patch 9.1.0764: [security]: use-after-free when closing a buffer
+
+Problem:  [security]: use-after-free when closing a buffer
+Solution: When splitting the window and editing a new buffer,
+          check whether the newly to be edited buffer has been marked
+          for deletion and abort in this case
+
+Github Advisory:
+https://github.com/vim/vim/security/advisories/GHSA-rj48-v4mq-j4vg
+
+Signed-off-by: Christian Brabandt <c...@256bit.org>
+(cherry picked from commit 51b62387be93c65fa56bbabe1c3c1ea5df187641)
+---
+ src/buffer.c         |  6 ++++++
+ src/ex_cmds.c        | 12 ++++++++++++
+ src/proto/buffer.pro |  1 +
+ 3 files changed, 19 insertions(+)
+
+diff --git a/src/buffer.c b/src/buffer.c
+index ff35729..530e6b6 100644
+--- a/src/buffer.c
++++ b/src/buffer.c
+@@ -487,6 +487,12 @@ can_unload_buffer(buf_T *buf)
+     return can_unload;
+ }
+ 
++    int
++buf_locked(buf_T *buf)
++{
++    return buf->b_locked || buf->b_locked_split;
++}
++
+ /*
+  * Close the link to a buffer.
+  * "action" is used when there is no longer a window for the buffer.
+diff --git a/src/ex_cmds.c b/src/ex_cmds.c
+index 5f017f4..219ea44 100644
+--- a/src/ex_cmds.c
++++ b/src/ex_cmds.c
+@@ -2730,6 +2730,18 @@ do_ecmd(
+       }
+       if (buf == NULL)
+           goto theend;
++      // autocommands try to edit a file that is goind to be removed,
++      // abort
++      if (buf_locked(buf))
++      {
++          // window was split, but not editing the new buffer,
++          // reset b_nwindows again
++          if (oldwin == NULL
++                  && curwin->w_buffer != NULL
++                  && curwin->w_buffer->b_nwindows > 1)
++              --curwin->w_buffer->b_nwindows;
++          goto theend;
++      }
+       if (curwin->w_alt_fnum == buf->b_fnum && prev_alt_fnum != 0)
+           // reusing the buffer, keep the old alternate file
+           curwin->w_alt_fnum = prev_alt_fnum;
+diff --git a/src/proto/buffer.pro b/src/proto/buffer.pro
+index 3a61027..dc68ca8 100644
+--- a/src/proto/buffer.pro
++++ b/src/proto/buffer.pro
+@@ -70,4 +70,5 @@ char_u *buf_get_fname(buf_T *buf);
+ void set_buflisted(int on);
+ int buf_contents_changed(buf_T *buf);
+ void wipe_buffer(buf_T *buf, int aucmd);
++int buf_locked(buf_T *buf);
+ /* vim: set ft=c : */
diff -Nru vim-9.0.1378/debian/patches/series vim-9.0.1378/debian/patches/series
--- vim-9.0.1378/debian/patches/series  2023-05-04 11:24:44.000000000 +0100
+++ vim-9.0.1378/debian/patches/series  2025-01-23 13:00:20.000000000 +0000
@@ -4,3 +4,11 @@
 debian/Document-Debian-s-decision-to-disable-modelines-by-defaul.patch
 patch-9.0.1499-using-uninitialized-memory-with-fuzzy-matc.patch
 Fix-GH-267-where-indent-after-a-sub-would-not-work.patch
+CVE-2023-2610.patch
+CVE-2023-4738.patch
+CVE-2023-4752.patch
+CVE-2023-4781.patch
+CVE-2023-5344.patch
+CVE-2024-22667.patch
+CVE-2024-43802.patch
+CVE-2024-47814.patch
diff -Nru vim-9.0.1378/debian/source/include-binaries 
vim-9.0.1378/debian/source/include-binaries
--- vim-9.0.1378/debian/source/include-binaries 1970-01-01 01:00:00.000000000 
+0100
+++ vim-9.0.1378/debian/source/include-binaries 2025-01-23 13:00:20.000000000 
+0000
@@ -0,0 +1,2 @@
+debian/patches/CVE-2023-4781.patch
+debian/patches/CVE-2024-43802.patch

Attachment: signature.asc
Description: PGP signature

Reply via email to