diff options
author | Bram Moolenaar <Bram@vim.org> | 2020-04-01 16:34:17 +0200 |
---|---|---|
committer | Bram Moolenaar <Bram@vim.org> | 2020-04-01 16:34:17 +0200 |
commit | 25b70c780a7e6063544e7f93c368fe403076f34e (patch) | |
tree | d7bab440c76f5710607417302f11203240c9f31f | |
parent | 05afceeddc4afbbca60e4e6a729a50d33d4b19f7 (diff) | |
download | vim-git-25b70c780a7e6063544e7f93c368fe403076f34e.tar.gz |
patch 8.2.0489: Vim9: memory leaksv8.2.0489
Problem: Vim9: memory leaks.
Solution: Free memory in the right place. Add hints for using asan.
-rw-r--r-- | src/Makefile | 5 | ||||
-rw-r--r-- | src/testdir/lsan-suppress.txt | 1 | ||||
-rw-r--r-- | src/version.c | 2 | ||||
-rw-r--r-- | src/vim9compile.c | 38 |
4 files changed, 39 insertions, 7 deletions
diff --git a/src/Makefile b/src/Makefile index 690ac3f8e..221b4f0de 100644 --- a/src/Makefile +++ b/src/Makefile @@ -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) diff --git a/src/testdir/lsan-suppress.txt b/src/testdir/lsan-suppress.txt index a3008bdce..f3d62b982 100644 --- a/src/testdir/lsan-suppress.txt +++ b/src/testdir/lsan-suppress.txt @@ -9,3 +9,4 @@ leak:libtinfo.so.5 leak:libperl.so.* leak:libpython*.so.* leak:libruby*.so.* +leak:libxcb*.so.* diff --git a/src/version.c b/src/version.c index 58180acc4..43f9e5943 100644 --- a/src/version.c +++ b/src/version.c @@ -739,6 +739,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 489, +/**/ 488, /**/ 487, diff --git a/src/vim9compile.c b/src/vim9compile.c index 3c3f5a163..64ebddfb9 100644 --- a/src/vim9compile.c +++ b/src/vim9compile.c @@ -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) @@ -3994,6 +3994,23 @@ new_scope(cctx_T *cctx, scopetype_T type) } /* + * 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) |