mirror of
https://github.com/vim/vim.git
synced 2025-09-23 03:43:49 -04:00
patch 8.2.3902: Vim9: double free with nested :def function
Problem: Vim9: double free with nested :def function. Solution: Pass "line_to_free" from compile_def_function() and make sure cmdlinep is valid.
This commit is contained in:
@@ -812,11 +812,13 @@ func_needs_compiling(ufunc_T *ufunc, compiletype_T compile_type)
|
||||
* Compile a nested :def command.
|
||||
*/
|
||||
static char_u *
|
||||
compile_nested_function(exarg_T *eap, cctx_T *cctx)
|
||||
compile_nested_function(exarg_T *eap, cctx_T *cctx, char_u **line_to_free)
|
||||
{
|
||||
int is_global = *eap->arg == 'g' && eap->arg[1] == ':';
|
||||
char_u *name_start = eap->arg;
|
||||
char_u *name_end = to_name_end(eap->arg, TRUE);
|
||||
int off;
|
||||
char_u *func_name;
|
||||
char_u *lambda_name;
|
||||
ufunc_T *ufunc;
|
||||
int r = FAIL;
|
||||
@@ -866,7 +868,17 @@ compile_nested_function(exarg_T *eap, cctx_T *cctx)
|
||||
lambda_name = vim_strsave(get_lambda_name());
|
||||
if (lambda_name == NULL)
|
||||
return NULL;
|
||||
ufunc = define_function(eap, lambda_name);
|
||||
|
||||
// This may free the current line, make a copy of the name.
|
||||
off = is_global ? 2 : 0;
|
||||
func_name = vim_strnsave(name_start + off, name_end - name_start - off);
|
||||
if (func_name == NULL)
|
||||
{
|
||||
r = FAIL;
|
||||
goto theend;
|
||||
}
|
||||
|
||||
ufunc = define_function(eap, lambda_name, line_to_free);
|
||||
|
||||
if (ufunc == NULL)
|
||||
{
|
||||
@@ -911,21 +923,14 @@ compile_nested_function(exarg_T *eap, cctx_T *cctx)
|
||||
|
||||
if (is_global)
|
||||
{
|
||||
char_u *func_name = vim_strnsave(name_start + 2,
|
||||
name_end - name_start - 2);
|
||||
|
||||
if (func_name == NULL)
|
||||
r = FAIL;
|
||||
else
|
||||
{
|
||||
r = generate_NEWFUNC(cctx, lambda_name, func_name);
|
||||
lambda_name = NULL;
|
||||
}
|
||||
r = generate_NEWFUNC(cctx, lambda_name, func_name);
|
||||
func_name = NULL;
|
||||
lambda_name = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Define a local variable for the function reference.
|
||||
lvar_T *lvar = reserve_local(cctx, name_start, name_end - name_start,
|
||||
lvar_T *lvar = reserve_local(cctx, func_name, name_end - name_start,
|
||||
TRUE, ufunc->uf_func_type);
|
||||
|
||||
if (lvar == NULL)
|
||||
@@ -937,6 +942,7 @@ compile_nested_function(exarg_T *eap, cctx_T *cctx)
|
||||
|
||||
theend:
|
||||
vim_free(lambda_name);
|
||||
vim_free(func_name);
|
||||
return r == FAIL ? NULL : (char_u *)"";
|
||||
}
|
||||
|
||||
@@ -2861,7 +2867,7 @@ compile_def_function(
|
||||
case CMD_def:
|
||||
case CMD_function:
|
||||
ea.arg = p;
|
||||
line = compile_nested_function(&ea, &cctx);
|
||||
line = compile_nested_function(&ea, &cctx, &line_to_free);
|
||||
break;
|
||||
|
||||
case CMD_return:
|
||||
|
Reference in New Issue
Block a user