vim-patch:8.2.1161: Vim9: using freed memory

Problem:    Vim9: using freed memory.
Solution:   Put pointer back in evalarg instead of freeing it.

8e2730a315

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.

6e13530ca0

Co-authored-by: Bram Moolenaar <Bram@vim.org>
This commit is contained in:
zeertzjq 2023-04-14 15:05:12 +08:00
parent 562840a2a1
commit cc7a50a9ae
3 changed files with 32 additions and 23 deletions

View File

@ -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;
}
}

View File

@ -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;

View File

@ -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;
}