0
0
mirror of https://github.com/vim/vim.git synced 2025-09-24 03:44:06 -04:00

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.
This commit is contained in:
Bram Moolenaar
2022-08-18 13:28:31 +01:00
parent 4875d6ab06
commit 91c7cbfe31
5 changed files with 77 additions and 59 deletions

View File

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