To: vim_dev@googlegroups.com Subject: Patch 8.2.3771 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ Patch 8.2.3771 Problem: Vim9: accessing freed memory when checking type. Solution: Make a copy of a function type. Files: src/structs.h, src/evalvars.c, src/vim9script.c, src/testdir/test_vim9_func.vim *** ../vim-8.2.3770/src/structs.h 2021-12-03 11:08:34.260842706 +0000 --- src/structs.h 2021-12-10 10:03:56.622486762 +0000 *************** *** 1809,1814 **** --- 1809,1815 ---- char_u *sv_name; // points into "sn_all_vars" di_key typval_T *sv_tv; // points into "sn_vars" or "sn_all_vars" di_tv type_T *sv_type; + int sv_type_allocated; // call free_type() for sv_type int sv_const; // 0, ASSIGN_CONST or ASSIGN_FINAL int sv_export; // "export let var = val" }; *** ../vim-8.2.3770/src/evalvars.c 2021-12-07 11:03:35.260224997 +0000 --- src/evalvars.c 2021-12-10 10:37:20.167846971 +0000 *************** *** 3291,3296 **** --- 3291,3297 ---- int vim9script = in_vim9script(); int var_in_vim9script; int flags = flags_arg; + int free_tv_arg = !copy; // free tv_arg if not used ht = find_var_ht(name, &varname); if (ht == NULL || *varname == NUL) *************** *** 3545,3550 **** --- 3546,3552 ---- dest_tv->v_lock = 0; init_tv(tv); } + free_tv_arg = FALSE; if (vim9script && type != NULL) { *************** *** 3573,3582 **** // if the reference count is up to one. That locks only literal // values. item_lock(dest_tv, DICT_MAXNEST, TRUE, TRUE); - return; failed: ! if (!copy) clear_tv(tv_arg); } --- 3575,3583 ---- // if the reference count is up to one. That locks only literal // values. item_lock(dest_tv, DICT_MAXNEST, TRUE, TRUE); failed: ! if (free_tv_arg) clear_tv(tv_arg); } *** ../vim-8.2.3770/src/vim9script.c 2021-11-26 17:36:48.008799188 +0000 --- src/vim9script.c 2021-12-10 10:15:37.557204820 +0000 *************** *** 268,273 **** --- 268,274 ---- hashitem_T *hi; sallvar_T *sav; sallvar_T *sav_next; + int idx; hash_lock(ht); todo = (int)ht->ht_used; *************** *** 293,298 **** --- 294,306 ---- hash_clear(ht); hash_init(ht); + for (idx = 0; idx < si->sn_var_vals.ga_len; ++idx) + { + svar_T *sv = ((svar_T *)si->sn_var_vals.ga_data) + idx; + + if (sv->sv_type_allocated) + free_type(sv->sv_type); + } ga_clear(&si->sn_var_vals); // existing commands using script variable indexes are no longer valid *************** *** 899,905 **** { if (*type == NULL) *type = typval2type(tv, get_copyID(), &si->sn_type_list, do_member); ! sv->sv_type = *type; } // let ex_export() know the export worked. --- 907,928 ---- { if (*type == NULL) *type = typval2type(tv, get_copyID(), &si->sn_type_list, do_member); ! if (sv->sv_type_allocated) ! free_type(sv->sv_type); ! if (*type != NULL && ((*type)->tt_type == VAR_FUNC ! || (*type)->tt_type == VAR_PARTIAL)) ! { ! // The type probably uses uf_type_list, which is cleared when the ! // function is freed, but the script variable may keep the type. ! // Make a copy to avoid using freed memory. ! sv->sv_type = alloc_type(*type); ! sv->sv_type_allocated = TRUE; ! } ! else ! { ! sv->sv_type = *type; ! sv->sv_type_allocated = FALSE; ! } } // let ex_export() know the export worked. *** ../vim-8.2.3770/src/testdir/test_vim9_func.vim 2021-12-09 14:23:40.261634977 +0000 --- src/testdir/test_vim9_func.vim 2021-12-10 10:32:22.144283133 +0000 *************** *** 1224,1229 **** --- 1224,1248 ---- CheckScriptSuccess(lines) enddef + def Test_lambda_type_allocated() + # Check that unreferencing a partial using a lambda can use the variable type + # after the lambda has been freed and does not leak memory. + var lines =<< trim END + vim9script + + func MyomniFunc1(val, findstart, base) + return a:findstart ? 0 : [] + endfunc + + var Lambda = (a, b) => MyomniFunc1(19, a, b) + &omnifunc = Lambda + Lambda = (a, b) => MyomniFunc1(20, a, b) + &omnifunc = string(Lambda) + Lambda = (a, b) => strlen(a) + END + CheckScriptSuccess(lines) + enddef + " Default arg and varargs def MyDefVarargs(one: string, two = 'foo', ...rest: list): string var res = one .. ',' .. two *** ../vim-8.2.3770/src/version.c 2021-12-09 21:07:07.604331912 +0000 --- src/version.c 2021-12-10 10:16:28.873200936 +0000 *************** *** 755,756 **** --- 755,758 ---- { /* Add new patch number below this line */ + /**/ + 3771, /**/ -- Q: What is the difference between open-source and commercial software? A: If you have a problem with commercial software you can call a phone number and they will tell you it might be solved in a future version. For open-source software there isn't a phone number to call, but you get the solution within a day. /// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net \\\ /// \\\ \\\ sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ /// \\\ help me help AIDS victims -- http://ICCF-Holland.org ///