Mercurial > vim
changeset 31435:8fe720031437 v9.0.1050
patch 9.0.1050: using freed memory when assigning to variable twice
Commit: https://github.com/vim/vim/commit/6342e2c5a6570231aefabd8e34c2f2cb22f6927a
Author: Bram Moolenaar <Bram@vim.org>
Date: Mon Dec 12 18:56:32 2022 +0000
patch 9.0.1050: using freed memory when assigning to variable twice
Problem: Using freed memory when assigning to variable twice.
Solution: Make copy of the list type. (closes https://github.com/vim/vim/issues/11691)
author | Bram Moolenaar <Bram@vim.org> |
---|---|
date | Mon, 12 Dec 2022 20:00:04 +0100 |
parents | 82f2f32bbe5e |
children | 8e20602d3d90 |
files | src/testdir/test_vim9_script.vim src/version.c src/vim9type.c |
diffstat | 3 files changed, 34 insertions(+), 1 deletions(-) [+] |
line wrap: on
line diff
--- a/src/testdir/test_vim9_script.vim +++ b/src/testdir/test_vim9_script.vim @@ -4519,6 +4519,36 @@ def Test_echo_uninit_variables() endif enddef +def Test_free_type_before_use() + # this rather complicated script was freeing a type before using it + var lines =<< trim END + vim9script + + def Scan(rel: list<dict<any>>): func(func(dict<any>)) + return (Emit: func(dict<any>)) => { + for t in rel + Emit(t) + endfor + } + enddef + + def Build(Cont: func(func(dict<any>))): list<dict<any>> + var rel: list<dict<any>> = [] + Cont((t) => { + add(rel, t) + }) + return rel + enddef + + var R = [{A: 0}] + var result = Scan(R)->Build() + result = Scan(R)->Build() + + assert_equal(R, result) + END + v9.CheckScriptSuccess(lines) +enddef + " Keep this last, it messes up highlighting. def Test_substitute_cmd() new
--- a/src/version.c +++ b/src/version.c @@ -696,6 +696,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 1050, +/**/ 1049, /**/ 1048,
--- a/src/vim9type.c +++ b/src/vim9type.c @@ -403,7 +403,8 @@ typval2type_int(typval_T *tv, int copyID if (l->lv_type != NULL && (l->lv_first == NULL || (flags & TVTT_MORE_SPECIFIC) == 0 || l->lv_type->tt_member != &t_any)) - return l->lv_type; + // make a copy, lv_type may be freed if the list is freed + return copy_type(l->lv_type, type_gap); if (l->lv_first == &range_list_item) return &t_list_number; if (l->lv_copyID == copyID)