1
0
forked from aniani/vim

patch 8.2.0489: Vim9: memory leaks

Problem:    Vim9: memory leaks.
Solution:   Free memory in the right place.  Add hints for using asan.
This commit is contained in:
Bram Moolenaar 2020-04-01 16:34:17 +02:00
parent 05afceeddc
commit 25b70c780a
4 changed files with 39 additions and 7 deletions

View File

@ -691,9 +691,12 @@ LINT_OPTIONS = -beprxzF
# Uncomment one of the next two lines to compile Vim with the
# address sanitizer or with the undefined sanitizer. Works with gcc and
# address sanitizer (asan) or with the undefined sanitizer. Works with gcc and
# clang. May make Vim twice as slow. Errors reported on stderr.
# More at: https://code.google.com/p/address-sanitizer/
# Useful environment variables:
# $ export ASAN_OPTIONS="print_stacktrace=1 log_path=asan"
# $ export LSAN_OPTIONS="suppressions=$cwd/testdir/lsan-suppress.txt"
#SANITIZER_CFLAGS = -g -O0 -fsanitize=address -fno-omit-frame-pointer
#SANITIZER_CFLAGS = -g -O0 -fsanitize=undefined -fno-omit-frame-pointer
SANITIZER_LIBS = $(SANITIZER_CFLAGS)

View File

@ -9,3 +9,4 @@ leak:libtinfo.so.5
leak:libperl.so.*
leak:libpython*.so.*
leak:libruby*.so.*
leak:libxcb*.so.*

View File

@ -738,6 +738,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
489,
/**/
488,
/**/

View File

@ -3500,7 +3500,7 @@ compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx)
if (cmdidx == CMD_const)
{
emsg(_(e_const_option));
return NULL;
goto theend;
}
if (is_decl)
{
@ -3513,7 +3513,7 @@ compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx)
{
// cannot happen?
emsg(_(e_letunexp));
return NULL;
goto theend;
}
cc = *p;
*p = NUL;
@ -3522,7 +3522,7 @@ compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx)
if (opt_type == -3)
{
semsg(_(e_unknown_option), arg);
return NULL;
goto theend;
}
if (opt_type == -2 || opt_type == 0)
type = &t_string;
@ -3543,7 +3543,7 @@ compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx)
if (!valid_yank_reg(arg[1], TRUE))
{
emsg_invreg(arg[1]);
return FAIL;
goto theend;
}
dest = dest_reg;
if (is_decl)
@ -3993,6 +3993,23 @@ new_scope(cctx_T *cctx, scopetype_T type)
return scope;
}
/*
* Free the current scope and go back to the outer scope.
*/
static void
drop_scope(cctx_T *cctx)
{
scope_T *scope = cctx->ctx_scope;
if (scope == NULL)
{
iemsg("calling drop_scope() without a scope");
return;
}
cctx->ctx_scope = scope->se_outer;
vim_free(scope);
}
/*
* Evaluate an expression that is a constant:
* has(arg)
@ -4412,7 +4429,6 @@ compile_endif(char_u *arg, cctx_T *cctx)
return NULL;
}
ifscope = &scope->se_u.se_if;
cctx->ctx_scope = scope->se_outer;
unwind_locals(cctx, scope->se_local_count);
if (scope->se_u.se_if.is_if_label >= 0)
@ -4425,7 +4441,7 @@ compile_endif(char_u *arg, cctx_T *cctx)
compile_fill_jump_to_end(&ifscope->is_end_label, cctx);
cctx->ctx_skip = FALSE;
vim_free(scope);
drop_scope(cctx);
return arg;
}
@ -4486,25 +4502,35 @@ compile_for(char_u *arg, cctx_T *cctx)
// Reserve a variable to store the loop iteration counter.
loop_idx = reserve_local(cctx, (char_u *)"", 0, FALSE, &t_number);
if (loop_idx < 0)
{
drop_scope(cctx);
return NULL;
}
// Reserve a variable to store "var"
var_idx = reserve_local(cctx, arg, varlen, FALSE, &t_any);
if (var_idx < 0)
{
drop_scope(cctx);
return NULL;
}
generate_STORENR(cctx, loop_idx, -1);
// compile "expr", it remains on the stack until "endfor"
arg = p;
if (compile_expr1(&arg, cctx) == FAIL)
{
drop_scope(cctx);
return NULL;
}
// now we know the type of "var"
vartype = ((type_T **)stack->ga_data)[stack->ga_len - 1];
if (vartype->tt_type != VAR_LIST)
{
emsg(_("E1024: need a List to iterate over"));
drop_scope(cctx);
return NULL;
}
if (vartype->tt_member->tt_type != VAR_UNKNOWN)