diff options
author | Bram Moolenaar <Bram@vim.org> | 2020-06-01 20:11:02 +0200 |
---|---|---|
committer | Bram Moolenaar <Bram@vim.org> | 2020-06-01 20:11:02 +0200 |
commit | 48b1c21809553d3463b5ed6c2b3bc6d335663bb6 (patch) | |
tree | b218c28062c484652ac4a387ed7e61f7bad2fc3d /src/list.c | |
parent | d6a77f95ee1e8ab69366d4f2a3412beef4cec914 (diff) | |
download | vim-git-48b1c21809553d3463b5ed6c2b3bc6d335663bb6.tar.gz |
patch 8.2.0882: leaking memory when using reduce()v8.2.0882
Problem: Leaking memory when using reduce().
Solution: Free the intermediate value.
Diffstat (limited to 'src/list.c')
-rw-r--r-- | src/list.c | 33 |
1 files changed, 20 insertions, 13 deletions
diff --git a/src/list.c b/src/list.c index 40a910b1e..baff6543d 100644 --- a/src/list.c +++ b/src/list.c @@ -2311,7 +2311,7 @@ f_reverse(typval_T *argvars, typval_T *rettv) void f_reduce(typval_T *argvars, typval_T *rettv) { - typval_T accum; + typval_T initial; char_u *func_name; partial_T *partial = NULL; funcexe_T funcexe; @@ -2343,6 +2343,7 @@ f_reduce(typval_T *argvars, typval_T *rettv) { list_T *l = argvars[0].vval.v_list; listitem_T *li = NULL; + int r; CHECK_LIST_MATERIALIZE(l); if (argvars[2].v_type == VAR_UNKNOWN) @@ -2352,24 +2353,26 @@ f_reduce(typval_T *argvars, typval_T *rettv) semsg(_(e_reduceempty), "List"); return; } - accum = l->lv_first->li_tv; + initial = l->lv_first->li_tv; li = l->lv_first->li_next; } else { - accum = argvars[2]; + initial = argvars[2]; if (l != NULL) li = l->lv_first; } - copy_tv(&accum, rettv); + copy_tv(&initial, rettv); for ( ; li != NULL; li = li->li_next) { - argv[0] = accum; + argv[0] = *rettv; argv[1] = li->li_tv; - if (call_func(func_name, -1, rettv, 2, argv, &funcexe) == FAIL) + rettv->v_type = VAR_UNKNOWN; + r = call_func(func_name, -1, rettv, 2, argv, &funcexe); + clear_tv(&argv[0]); + if (r == FAIL) return; - accum = *rettv; } } else @@ -2384,27 +2387,31 @@ f_reduce(typval_T *argvars, typval_T *rettv) semsg(_(e_reduceempty), "Blob"); return; } - accum.v_type = VAR_NUMBER; - accum.vval.v_number = blob_get(b, 0); + initial.v_type = VAR_NUMBER; + initial.vval.v_number = blob_get(b, 0); i = 1; } + else if (argvars[2].v_type != VAR_NUMBER) + { + emsg(_(e_number_exp)); + return; + } else { - accum = argvars[2]; + initial = argvars[2]; i = 0; } - copy_tv(&accum, rettv); + copy_tv(&initial, rettv); if (b != NULL) { for ( ; i < b->bv_ga.ga_len; i++) { - argv[0] = accum; + argv[0] = *rettv; argv[1].v_type = VAR_NUMBER; argv[1].vval.v_number = blob_get(b, i); if (call_func(func_name, -1, rettv, 2, argv, &funcexe) == FAIL) return; - accum = *rettv; } } } |