diff --git a/backport-CVE-2022-2889.patch b/backport-CVE-2022-2889.patch new file mode 100644 index 0000000000000000000000000000000000000000..71014cd97b0b16dc4a89f9c258e4d18f79d71829 --- /dev/null +++ b/backport-CVE-2022-2889.patch @@ -0,0 +1,245 @@ +From 91c7cbfe31bbef57d5fcf7d76989fc159f73ef15 Mon Sep 17 00:00:00 2001 +From: Bram Moolenaar +Date: Thu, 18 Aug 2022 13:28:31 +0100 +Subject: [PATCH] patch 9.0.0225: using freed memory with multiple line breaks + in expression + +Problem: Using freed memory with multiple line breaks in expression. +Solution: Free eval_tofree later. +--- + src/eval.c | 102 ++++++++++++++++++------------- + src/proto/eval.pro | 4 +- + src/testdir/test_vim9_script.vim | 13 ++++ + src/userfunc.c | 15 ----- + 4 files changed, 75 insertions(+), 59 deletions(-) + +diff --git a/src/eval.c b/src/eval.c +index 42b883e..60daca5 100644 +--- a/src/eval.c ++++ b/src/eval.c +@@ -353,6 +353,63 @@ eval_to_string_skip( + return retval; + } + ++/* ++ * Initialize "evalarg" for use. ++ */ ++ void ++init_evalarg(evalarg_T *evalarg) ++{ ++ CLEAR_POINTER(evalarg); ++ ga_init2(&evalarg->eval_tofree_ga, sizeof(char_u *), 20); ++} ++ ++/* ++ * If "evalarg->eval_tofree" is not NULL free it later. ++ * Caller is expected to overwrite "evalarg->eval_tofree" next. ++ */ ++ static void ++free_eval_tofree_later(evalarg_T *evalarg) ++{ ++ if (evalarg->eval_tofree != NULL) ++ { ++ if (ga_grow(&evalarg->eval_tofree_ga, 1) == OK) ++ ((char_u **)evalarg->eval_tofree_ga.ga_data) ++ [evalarg->eval_tofree_ga.ga_len++] ++ = evalarg->eval_tofree; ++ else ++ vim_free(evalarg->eval_tofree); ++ } ++} ++ ++/* ++ * After using "evalarg" filled from "eap": free the memory. ++ */ ++ void ++clear_evalarg(evalarg_T *evalarg, exarg_T *eap) ++{ ++ if (evalarg != NULL) ++ { ++ if (evalarg->eval_tofree != NULL) ++ { ++ if (eap != NULL) ++ { ++ // We may need to keep the original command line, e.g. for ++ // ":let" it has the variable names. But we may also need the ++ // new one, "nextcmd" points into it. Keep both. ++ vim_free(eap->cmdline_tofree); ++ eap->cmdline_tofree = *eap->cmdlinep; ++ *eap->cmdlinep = evalarg->eval_tofree; ++ } ++ else ++ vim_free(evalarg->eval_tofree); ++ evalarg->eval_tofree = NULL; ++ } ++ ++ ga_clear_strings(&evalarg->eval_tofree_ga); ++ VIM_CLEAR(evalarg->eval_tofree_lambda); ++ } ++} ++ + /* + * Skip over an expression at "*pp". + * Return FAIL for an error, OK otherwise. +@@ -435,8 +492,8 @@ skip_expr_concatenate( + // Do not free the first line, the caller can still use it. + *((char_u **)gap->ga_data) = NULL; + // Do not free the last line, "arg" points into it, free it +- // later. +- vim_free(evalarg->eval_tofree); ++ // later. Also free "eval_tofree" later if needed. ++ free_eval_tofree_later(evalarg); + evalarg->eval_tofree = + ((char_u **)gap->ga_data)[gap->ga_len - 1]; + ((char_u **)gap->ga_data)[gap->ga_len - 1] = NULL; +@@ -2274,7 +2331,7 @@ eval_next_line(char_u *arg, evalarg_T *evalarg) + } + else if (evalarg->eval_cookie != NULL) + { +- vim_free(evalarg->eval_tofree); ++ free_eval_tofree_later(evalarg); + evalarg->eval_tofree = line; + } + +@@ -2301,45 +2358,6 @@ skipwhite_and_linebreak(char_u *arg, evalarg_T *evalarg) + return p; + } + +-/* +- * Initialize "evalarg" for use. +- */ +- void +-init_evalarg(evalarg_T *evalarg) +-{ +- CLEAR_POINTER(evalarg); +- ga_init2(&evalarg->eval_tofree_ga, sizeof(char_u *), 20); +-} +- +-/* +- * After using "evalarg" filled from "eap": free the memory. +- */ +- void +-clear_evalarg(evalarg_T *evalarg, exarg_T *eap) +-{ +- if (evalarg != NULL) +- { +- if (evalarg->eval_tofree != NULL) +- { +- if (eap != NULL) +- { +- // We may need to keep the original command line, e.g. for +- // ":let" it has the variable names. But we may also need the +- // new one, "nextcmd" points into it. Keep both. +- vim_free(eap->cmdline_tofree); +- eap->cmdline_tofree = *eap->cmdlinep; +- *eap->cmdlinep = evalarg->eval_tofree; +- } +- else +- vim_free(evalarg->eval_tofree); +- evalarg->eval_tofree = NULL; +- } +- +- ga_clear_strings(&evalarg->eval_tofree_ga); +- VIM_CLEAR(evalarg->eval_tofree_lambda); +- } +-} +- + /* + * The "evaluate" argument: When FALSE, the argument is only parsed but not + * executed. The function may return OK, but the rettv will be of type +diff --git a/src/proto/eval.pro b/src/proto/eval.pro +index e6cd892..27a13c9 100644 +--- a/src/proto/eval.pro ++++ b/src/proto/eval.pro +@@ -9,6 +9,8 @@ int eval_expr_valid_arg(typval_T *tv); + int eval_expr_typval(typval_T *expr, typval_T *argv, int argc, typval_T *rettv); + int eval_expr_to_bool(typval_T *expr, int *error); + char_u *eval_to_string_skip(char_u *arg, exarg_T *eap, int skip); ++void init_evalarg(evalarg_T *evalarg); ++void clear_evalarg(evalarg_T *evalarg, exarg_T *eap); + int skip_expr(char_u **pp, evalarg_T *evalarg); + int skip_expr_concatenate(char_u **arg, char_u **start, char_u **end, evalarg_T *evalarg); + char_u *typval2string(typval_T *tv, int convert); +@@ -34,8 +36,6 @@ int pattern_match(char_u *pat, char_u *text, int ic); + char_u *eval_next_non_blank(char_u *arg, evalarg_T *evalarg, int *getnext); + char_u *eval_next_line(char_u *arg, evalarg_T *evalarg); + char_u *skipwhite_and_linebreak(char_u *arg, evalarg_T *evalarg); +-void init_evalarg(evalarg_T *evalarg); +-void clear_evalarg(evalarg_T *evalarg, exarg_T *eap); + int eval0(char_u *arg, typval_T *rettv, exarg_T *eap, evalarg_T *evalarg); + int eval0_retarg(char_u *arg, typval_T *rettv, exarg_T *eap, evalarg_T *evalarg, char_u **retarg); + int eval1(char_u **arg, typval_T *rettv, evalarg_T *evalarg); +diff --git a/src/testdir/test_vim9_script.vim b/src/testdir/test_vim9_script.vim +index 75b3e9c..c09c0d2 100644 +--- a/src/testdir/test_vim9_script.vim ++++ b/src/testdir/test_vim9_script.vim +@@ -1560,6 +1560,19 @@ def Test_func_redefine_fails() + v9.CheckScriptFailure(lines, 'E1073:') + enddef + ++def Test_lambda_split() ++ # this was using freed memory, because of the split expression ++ var lines =<< trim END ++ vim9script ++ try ++ 0 ++ 0->(0 ++ ->a.0( ++ ->u ++ END ++ v9.CheckScriptFailure(lines, 'E1050:') ++enddef ++ + def Test_fixed_size_list() + # will be allocated as one piece of memory, check that changes work + var l = [1, 2, 3, 4] +diff --git a/src/userfunc.c b/src/userfunc.c +index 9b960b7..3777e03 100644 +--- a/src/userfunc.c ++++ b/src/userfunc.c +@@ -1371,7 +1371,6 @@ get_lambda_tv( + char_u *start, *end; + int *old_eval_lavars = eval_lavars_used; + int eval_lavars = FALSE; +- char_u *tofree1 = NULL; + char_u *tofree2 = NULL; + int equal_arrow = **arg == '('; + int white_error = FALSE; +@@ -1456,12 +1455,6 @@ get_lambda_tv( + ret = skip_expr_concatenate(arg, &start, &end, evalarg); + if (ret == FAIL) + goto errret; +- if (evalarg != NULL) +- { +- // avoid that the expression gets freed when another line break follows +- tofree1 = evalarg->eval_tofree; +- evalarg->eval_tofree = NULL; +- } + + if (!equal_arrow) + { +@@ -1584,10 +1577,6 @@ get_lambda_tv( + + theend: + eval_lavars_used = old_eval_lavars; +- if (evalarg != NULL && evalarg->eval_tofree == NULL) +- evalarg->eval_tofree = tofree1; +- else +- vim_free(tofree1); + vim_free(tofree2); + if (types_optional) + ga_clear_strings(&argtypes); +@@ -1606,10 +1595,6 @@ errret: + } + vim_free(fp); + vim_free(pt); +- if (evalarg != NULL && evalarg->eval_tofree == NULL) +- evalarg->eval_tofree = tofree1; +- else +- vim_free(tofree1); + vim_free(tofree2); + eval_lavars_used = old_eval_lavars; + return FAIL; +-- +2.36.1 + diff --git a/backport-CVE-2022-2923.patch b/backport-CVE-2022-2923.patch new file mode 100644 index 0000000000000000000000000000000000000000..774c45459c296a6eedce301ad3ffff458efc4ed5 --- /dev/null +++ b/backport-CVE-2022-2923.patch @@ -0,0 +1,56 @@ +From 6669de1b235843968e88844ca6d3c8dec4b01a9e Mon Sep 17 00:00:00 2001 +From: Bram Moolenaar +Date: Sun, 21 Aug 2022 20:33:47 +0100 +Subject: [PATCH] patch 9.0.0240: crash when using ":mkspell" with an +empty + .dic file + +Problem: Crash when using ":mkspell" with an empty .dic file. +Solution: Check for an empty word tree. +--- + src/spellfile.c | 4 +++- + src/testdir/test_spellfile.vim | 12 ++++++++++++ + 2 files changed, 15 insertions(+), 1 deletion(-) + +diff --git a/src/spellfile.c b/src/spellfile.c +index 4a0de52..a4407fa 100644 +--- a/src/spellfile.c ++++ b/src/spellfile.c +@@ -5585,10 +5585,12 @@ sug_filltree(spellinfo_T *spin, slang_T *slang) + + /* + * Go through the whole case-folded tree, soundfold each word and put it +- * in the trie. ++ * in the trie. Bail out if the tree is empty. + */ + byts = slang->sl_fbyts; + idxs = slang->sl_fidxs; ++ if (byts == NULL || idxs == NULL) ++ return FAIL; + + arridx[0] = 0; + curi[0] = 1; +diff --git a/src/testdir/test_spellfile.vim b/src/testdir/test_spellfile.vim +index 38d1ec0..e81aa65 100644 +--- a/src/testdir/test_spellfile.vim ++++ b/src/testdir/test_spellfile.vim +@@ -1160,4 +1160,16 @@ func Test_mkspellmem_opt() + call assert_fails('set mkspellmem=1000,50,0', 'E474:') + endfunc + ++" this was using a NULL pointer ++func Test_mkspell_empty_dic() ++ call writefile(['1'], 'XtestEmpty.dic') ++ call writefile(['SOFOFROM abcd', 'SOFOTO ABCD', 'SAL CIA X'], 'XtestEmpty.aff') ++ mkspell! XtestEmpty.spl XtestEmpty ++ ++ call delete('XtestEmpty.dic') ++ call delete('XtestEmpty.aff') ++ call delete('XtestEmpty.spl') ++endfunc ++ ++ + " vim: shiftwidth=2 sts=2 expandtab +-- +2.36.1 + diff --git a/backport-CVE-2022-2946.patch b/backport-CVE-2022-2946.patch new file mode 100644 index 0000000000000000000000000000000000000000..91b7544ad9c3ee834918eab613797e628a662b9d --- /dev/null +++ b/backport-CVE-2022-2946.patch @@ -0,0 +1,71 @@ +From adce965162dd89bf29ee0e5baf53652e7515762c Mon Sep 17 00:00:00 2001 +From: Bram Moolenaar +Date: Mon, 22 Aug 2022 16:35:45 +0100 +Subject: [PATCH] patch 9.0.0246: using freed memory when 'tagfunc' deletes the + buffer + +Problem: Using freed memory when 'tagfunc' deletes the buffer. +Solution: Make a copy of the tag name. +--- + src/tag.c | 9 ++++++++- + src/testdir/test_tagfunc.vim | 12 ++++++++++++ + 2 files changed, 20 insertions(+), 1 deletion(-) + +diff --git a/src/tag.c b/src/tag.c +index 8a351cc..02f0818 100644 +--- a/src/tag.c ++++ b/src/tag.c +@@ -281,6 +281,7 @@ do_tag( + char_u *buf_ffname = curbuf->b_ffname; // name to use for + // priority computation + int use_tfu = 1; ++ char_u *tofree = NULL; + + // remember the matches for the last used tag + static int num_matches = 0; +@@ -630,7 +631,12 @@ do_tag( + * When desired match not found yet, try to find it (and others). + */ + if (use_tagstack) +- name = tagstack[tagstackidx].tagname; ++ { ++ // make a copy, the tagstack may change in 'tagfunc' ++ name = vim_strsave(tagstack[tagstackidx].tagname); ++ vim_free(tofree); ++ tofree = name; ++ } + #if defined(FEAT_QUICKFIX) + else if (g_do_tagpreview != 0) + name = ptag_entry.tagname; +@@ -922,6 +928,7 @@ end_do_tag: + g_do_tagpreview = 0; // don't do tag preview next time + # endif + ++ vim_free(tofree); + #ifdef FEAT_CSCOPE + return jumped_to_tag; + #else +diff --git a/src/testdir/test_tagfunc.vim b/src/testdir/test_tagfunc.vim +index 05d8473..9582612 100644 +--- a/src/testdir/test_tagfunc.vim ++++ b/src/testdir/test_tagfunc.vim +@@ -389,4 +389,16 @@ func Test_tagfunc_callback() + %bw! + endfunc + ++func Test_tagfunc_wipes_buffer() ++ func g:Tag0unc0(t,f,o) ++ bwipe ++ endfunc ++ set tagfunc=g:Tag0unc0 ++ new ++ cal assert_fails('tag 0', 'E987:') ++ ++ delfunc g:Tag0unc0 ++ set tagfunc= ++endfunc ++ + " vim: shiftwidth=2 sts=2 expandtab +-- +1.8.3.1 + diff --git a/vim.spec b/vim.spec index c15321b18c84a0fd133a801426c2d343cb0f5dba..32c1ccd3194015dc12ee305873b52daf5252e15e 100644 --- a/vim.spec +++ b/vim.spec @@ -12,7 +12,7 @@ Name: vim Epoch: 2 Version: 9.0 -Release: 6 +Release: 7 Summary: Vim is a highly configurable text editor for efficiently creating and changing any kind of text. License: Vim and MIT URL: http://www.vim.org @@ -53,6 +53,9 @@ Patch6022: backport-CVE-2022-2845.patch Patch6023: backport-CVE-2022-2849.patch Patch6024: backport-CVE-2022-2862.patch Patch6025: backport-CVE-2022-2874.patch +Patch6026: backport-CVE-2022-2889.patch +Patch6027: backport-CVE-2022-2923.patch +Patch6028: backport-CVE-2022-2946.patch Patch9000: bugfix-rm-modify-info-version.patch @@ -446,6 +449,12 @@ popd %{_mandir}/man1/evim.* %changelog +* Sat Aug 20 2022 shixuantong - 2:9.0-7 +- Type:CVE +- ID:CVE-2022-2889 CVE-2022-2923 CVE-2022-2946 +- SUG:NA +- DESC:fix CVE-2022-2889 CVE-2022-2923 CVE-2022-2946 + * Thu Aug 18 2022 shixuantong - 2:9.0-6 - Type:CVE - ID:CVE-2022-2816 CVE-2022-2817 CVE-2022-2819 CVE-2022-2845 CVE-2022-2849 CVE-2022-2862 CVE-2022-2874