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:
parent
05afceeddc
commit
25b70c780a
@ -691,9 +691,12 @@ LINT_OPTIONS = -beprxzF
|
|||||||
|
|
||||||
|
|
||||||
# Uncomment one of the next two lines to compile Vim with the
|
# 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.
|
# clang. May make Vim twice as slow. Errors reported on stderr.
|
||||||
# More at: https://code.google.com/p/address-sanitizer/
|
# 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=address -fno-omit-frame-pointer
|
||||||
#SANITIZER_CFLAGS = -g -O0 -fsanitize=undefined -fno-omit-frame-pointer
|
#SANITIZER_CFLAGS = -g -O0 -fsanitize=undefined -fno-omit-frame-pointer
|
||||||
SANITIZER_LIBS = $(SANITIZER_CFLAGS)
|
SANITIZER_LIBS = $(SANITIZER_CFLAGS)
|
||||||
|
@ -9,3 +9,4 @@ leak:libtinfo.so.5
|
|||||||
leak:libperl.so.*
|
leak:libperl.so.*
|
||||||
leak:libpython*.so.*
|
leak:libpython*.so.*
|
||||||
leak:libruby*.so.*
|
leak:libruby*.so.*
|
||||||
|
leak:libxcb*.so.*
|
||||||
|
@ -738,6 +738,8 @@ static char *(features[]) =
|
|||||||
|
|
||||||
static int included_patches[] =
|
static int included_patches[] =
|
||||||
{ /* Add new patch number below this line */
|
{ /* Add new patch number below this line */
|
||||||
|
/**/
|
||||||
|
489,
|
||||||
/**/
|
/**/
|
||||||
488,
|
488,
|
||||||
/**/
|
/**/
|
||||||
|
@ -3500,7 +3500,7 @@ compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx)
|
|||||||
if (cmdidx == CMD_const)
|
if (cmdidx == CMD_const)
|
||||||
{
|
{
|
||||||
emsg(_(e_const_option));
|
emsg(_(e_const_option));
|
||||||
return NULL;
|
goto theend;
|
||||||
}
|
}
|
||||||
if (is_decl)
|
if (is_decl)
|
||||||
{
|
{
|
||||||
@ -3513,7 +3513,7 @@ compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx)
|
|||||||
{
|
{
|
||||||
// cannot happen?
|
// cannot happen?
|
||||||
emsg(_(e_letunexp));
|
emsg(_(e_letunexp));
|
||||||
return NULL;
|
goto theend;
|
||||||
}
|
}
|
||||||
cc = *p;
|
cc = *p;
|
||||||
*p = NUL;
|
*p = NUL;
|
||||||
@ -3522,7 +3522,7 @@ compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx)
|
|||||||
if (opt_type == -3)
|
if (opt_type == -3)
|
||||||
{
|
{
|
||||||
semsg(_(e_unknown_option), arg);
|
semsg(_(e_unknown_option), arg);
|
||||||
return NULL;
|
goto theend;
|
||||||
}
|
}
|
||||||
if (opt_type == -2 || opt_type == 0)
|
if (opt_type == -2 || opt_type == 0)
|
||||||
type = &t_string;
|
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))
|
if (!valid_yank_reg(arg[1], TRUE))
|
||||||
{
|
{
|
||||||
emsg_invreg(arg[1]);
|
emsg_invreg(arg[1]);
|
||||||
return FAIL;
|
goto theend;
|
||||||
}
|
}
|
||||||
dest = dest_reg;
|
dest = dest_reg;
|
||||||
if (is_decl)
|
if (is_decl)
|
||||||
@ -3993,6 +3993,23 @@ new_scope(cctx_T *cctx, scopetype_T type)
|
|||||||
return scope;
|
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:
|
* Evaluate an expression that is a constant:
|
||||||
* has(arg)
|
* has(arg)
|
||||||
@ -4412,7 +4429,6 @@ compile_endif(char_u *arg, cctx_T *cctx)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
ifscope = &scope->se_u.se_if;
|
ifscope = &scope->se_u.se_if;
|
||||||
cctx->ctx_scope = scope->se_outer;
|
|
||||||
unwind_locals(cctx, scope->se_local_count);
|
unwind_locals(cctx, scope->se_local_count);
|
||||||
|
|
||||||
if (scope->se_u.se_if.is_if_label >= 0)
|
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);
|
compile_fill_jump_to_end(&ifscope->is_end_label, cctx);
|
||||||
cctx->ctx_skip = FALSE;
|
cctx->ctx_skip = FALSE;
|
||||||
|
|
||||||
vim_free(scope);
|
drop_scope(cctx);
|
||||||
return arg;
|
return arg;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4486,25 +4502,35 @@ compile_for(char_u *arg, cctx_T *cctx)
|
|||||||
// Reserve a variable to store the loop iteration counter.
|
// Reserve a variable to store the loop iteration counter.
|
||||||
loop_idx = reserve_local(cctx, (char_u *)"", 0, FALSE, &t_number);
|
loop_idx = reserve_local(cctx, (char_u *)"", 0, FALSE, &t_number);
|
||||||
if (loop_idx < 0)
|
if (loop_idx < 0)
|
||||||
|
{
|
||||||
|
drop_scope(cctx);
|
||||||
return NULL;
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
// Reserve a variable to store "var"
|
// Reserve a variable to store "var"
|
||||||
var_idx = reserve_local(cctx, arg, varlen, FALSE, &t_any);
|
var_idx = reserve_local(cctx, arg, varlen, FALSE, &t_any);
|
||||||
if (var_idx < 0)
|
if (var_idx < 0)
|
||||||
|
{
|
||||||
|
drop_scope(cctx);
|
||||||
return NULL;
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
generate_STORENR(cctx, loop_idx, -1);
|
generate_STORENR(cctx, loop_idx, -1);
|
||||||
|
|
||||||
// compile "expr", it remains on the stack until "endfor"
|
// compile "expr", it remains on the stack until "endfor"
|
||||||
arg = p;
|
arg = p;
|
||||||
if (compile_expr1(&arg, cctx) == FAIL)
|
if (compile_expr1(&arg, cctx) == FAIL)
|
||||||
|
{
|
||||||
|
drop_scope(cctx);
|
||||||
return NULL;
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
// now we know the type of "var"
|
// now we know the type of "var"
|
||||||
vartype = ((type_T **)stack->ga_data)[stack->ga_len - 1];
|
vartype = ((type_T **)stack->ga_data)[stack->ga_len - 1];
|
||||||
if (vartype->tt_type != VAR_LIST)
|
if (vartype->tt_type != VAR_LIST)
|
||||||
{
|
{
|
||||||
emsg(_("E1024: need a List to iterate over"));
|
emsg(_("E1024: need a List to iterate over"));
|
||||||
|
drop_scope(cctx);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
if (vartype->tt_member->tt_type != VAR_UNKNOWN)
|
if (vartype->tt_member->tt_type != VAR_UNKNOWN)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user