From cc7a50a9ae9384167bd0fc2ee2eb7f1b31842f27 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Fri, 14 Apr 2023 15:05:12 +0800 Subject: [PATCH] vim-patch:8.2.1161: Vim9: using freed memory Problem: Vim9: using freed memory. Solution: Put pointer back in evalarg instead of freeing it. https://github.com/vim/vim/commit/8e2730a315b8b06192f5fc822dc218dbb3cff7ae Omit eval_tofree_lambda: Vim9 script only. N/A patches for version.c: vim-patch:8.2.1163: build error Problem: Build error. Solution: Add missing change to globals. https://github.com/vim/vim/commit/6e13530ca03dd9cad245221177dd65f712211448 Co-authored-by: Bram Moolenaar --- src/nvim/eval.c | 26 ++++++++++++++------------ src/nvim/eval.h | 2 +- src/nvim/eval/userfunc.c | 27 +++++++++++++++++---------- 3 files changed, 32 insertions(+), 23 deletions(-) diff --git a/src/nvim/eval.c b/src/nvim/eval.c index ec3c2b5e85..9660157592 100644 --- a/src/nvim/eval.c +++ b/src/nvim/eval.c @@ -2259,21 +2259,23 @@ static int eval_func(char **const arg, evalarg_T *const evalarg, char *const nam return ret; } -/// After using "evalarg" filled from "eap" free the memory. +/// After using "evalarg" filled from "eap": free the memory. void clear_evalarg(evalarg_T *evalarg, exarg_T *eap) { - if (evalarg != NULL && 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. - xfree(eap->cmdline_tofree); - eap->cmdline_tofree = *eap->cmdlinep; - *eap->cmdlinep = evalarg->eval_tofree; - } else { - xfree(evalarg->eval_tofree); + 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. + xfree(eap->cmdline_tofree); + eap->cmdline_tofree = *eap->cmdlinep; + *eap->cmdlinep = evalarg->eval_tofree; + } else { + xfree(evalarg->eval_tofree); + } + evalarg->eval_tofree = NULL; } - evalarg->eval_tofree = NULL; } } diff --git a/src/nvim/eval.h b/src/nvim/eval.h index 4e0eb6ebb8..e9cdb108a8 100644 --- a/src/nvim/eval.h +++ b/src/nvim/eval.h @@ -275,7 +275,7 @@ typedef struct { LineGetter eval_getline; void *eval_cookie; ///< argument for eval_getline() - /// pointer to the line obtained with getsourceline() + /// pointer to the last line obtained with getsourceline() char *eval_tofree; } evalarg_T; diff --git a/src/nvim/eval/userfunc.c b/src/nvim/eval/userfunc.c index 3fc34471bf..9440ceb36e 100644 --- a/src/nvim/eval/userfunc.c +++ b/src/nvim/eval/userfunc.c @@ -261,15 +261,14 @@ int get_lambda_tv(char **arg, typval_T *rettv, evalarg_T *evalarg) partial_T *pt = NULL; int varargs; int ret; - char *start = skipwhite(*arg + 1); - char *s, *e; bool *old_eval_lavars = eval_lavars_used; bool eval_lavars = false; char *tofree = NULL; // First, check if this is a lambda expression. "->" must exists. - ret = get_function_args(&start, '-', NULL, NULL, NULL, true); - if (ret == FAIL || *start != '>') { + char *s = skipwhite(*arg + 1); + ret = get_function_args(&s, '-', NULL, NULL, NULL, true); + if (ret == FAIL || *s != '>') { return NOTDONE; } @@ -292,8 +291,9 @@ int get_lambda_tv(char **arg, typval_T *rettv, evalarg_T *evalarg) // Get the start and the end of the expression. *arg = skipwhite((*arg) + 1); - s = *arg; + char *start = *arg; ret = skip_expr(arg, evalarg); + char *end = *arg; if (ret == FAIL) { goto errret; } @@ -303,7 +303,6 @@ int get_lambda_tv(char **arg, typval_T *rettv, evalarg_T *evalarg) evalarg->eval_tofree = NULL; } - e = *arg; *arg = skipwhite(*arg); if (**arg != '}') { semsg(_("E451: Expected }: %s"), *arg); @@ -325,11 +324,11 @@ int get_lambda_tv(char **arg, typval_T *rettv, evalarg_T *evalarg) ga_grow(&newlines, 1); // Add "return " before the expression. - size_t len = (size_t)(7 + e - s + 1); + size_t len = (size_t)(7 + end - start + 1); p = xmalloc(len); ((char **)(newlines.ga_data))[newlines.ga_len++] = p; STRCPY(p, "return "); - xstrlcpy(p + 7, s, (size_t)(e - s) + 1); + xstrlcpy(p + 7, start, (size_t)(end - start) + 1); if (strstr(p + 7, "a:") == NULL) { // No a: variables are used for sure. flags |= FC_NOARGS; @@ -367,14 +366,22 @@ int get_lambda_tv(char **arg, typval_T *rettv, evalarg_T *evalarg) } eval_lavars_used = old_eval_lavars; - xfree(tofree); + if (evalarg->eval_tofree == NULL) { + evalarg->eval_tofree = tofree; + } else { + xfree(tofree); + } return OK; errret: ga_clear_strings(&newargs); xfree(fp); xfree(pt); - xfree(tofree); + if (evalarg->eval_tofree == NULL) { + evalarg->eval_tofree = tofree; + } else { + xfree(tofree); + } eval_lavars_used = old_eval_lavars; return FAIL; }