Patch 8.2.3771

4 views
Skip to first unread message

Bram Moolenaar

unread,
Dec 10, 2021, 5:38:15 AM12/10/21
to vim...@googlegroups.com

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>): 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 -- Br...@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 ///
Reply all
Reply to author
Forward
0 new messages