Mercurial > vim
diff src/vim9compile.c @ 26747:a8a4e1e7b111 v8.2.3902
patch 8.2.3902: Vim9: double free with nested :def function
Commit: https://github.com/vim/vim/commit/9c23f9bb5fe435b28245ba8ac65aa0ca6b902c04
Author: Bram Moolenaar <Bram@vim.org>
Date: Sun Dec 26 14:23:22 2021 +0000
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.
author | Bram Moolenaar <Bram@vim.org> |
---|---|
date | Sun, 26 Dec 2021 15:30:02 +0100 |
parents | b969fdb8cd46 |
children | 30d8377ea1b1 |
line wrap: on
line diff
--- a/src/vim9compile.c +++ b/src/vim9compile.c @@ -812,11 +812,13 @@ func_needs_compiling(ufunc_T *ufunc, com * 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, cc 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, cc 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, cc 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: