Version in base suite: 9.0.1378-2 Base version: vim_9.0.1378-2 Target version: vim_9.0.1378-2+deb12u1 Base file: /srv/ftp-master.debian.org/ftp/pool/main/v/vim/vim_9.0.1378-2.dsc Target file: /srv/ftp-master.debian.org/policy/pool/main/v/vim/vim_9.0.1378-2+deb12u1.dsc /srv/release.debian.org/tmp/4hfHkdPJZn/vim-9.0.1378/debian/patches/CVE-2023-4781.patch |binary /srv/release.debian.org/tmp/4hfHkdPJZn/vim-9.0.1378/debian/patches/CVE-2024-43802.patch |binary vim-9.0.1378/debian/changelog | 18 vim-9.0.1378/debian/patches/CVE-2023-2610.patch | 111 ++ vim-9.0.1378/debian/patches/CVE-2023-4738.patch | 74 + vim-9.0.1378/debian/patches/CVE-2023-4752.patch | 55 + vim-9.0.1378/debian/patches/CVE-2023-5344.patch | 58 + vim-9.0.1378/debian/patches/CVE-2024-22667.patch | 392 ++++++++++ vim-9.0.1378/debian/patches/CVE-2024-47814.patch | 70 + vim-9.0.1378/debian/patches/series | 8 vim-9.0.1378/debian/source/include-binaries | 2 11 files changed, 788 insertions(+) diff -Nru vim-9.0.1378/debian/changelog vim-9.0.1378/debian/changelog --- vim-9.0.1378/debian/changelog 2023-05-04 10:24:44.000000000 +0000 +++ 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 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 00:00:00.000000000 +0000 +++ 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 +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 00:00:00.000000000 +0000 +++ 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 +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 +(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 00:00:00.000000000 +0000 +++ 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 +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 +(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 /srv/release.debian.org/tmp/tInpM5cfq3/vim-9.0.1378/debian/patches/CVE-2023-4781.patch and /srv/release.debian.org/tmp/4hfHkdPJZn/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 00:00:00.000000000 +0000 +++ 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 +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 +(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 00:00:00.000000000 +0000 +++ 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 +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 +(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: pm31 3" +\ 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 /srv/release.debian.org/tmp/tInpM5cfq3/vim-9.0.1378/debian/patches/CVE-2024-43802.patch and /srv/release.debian.org/tmp/4hfHkdPJZn/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 00:00:00.000000000 +0000 +++ 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 +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 +(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 10:24:44.000000000 +0000 +++ 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 00:00:00.000000000 +0000 +++ 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