0
0
mirror of https://github.com/vim/vim.git synced 2025-09-26 04:04:07 -04:00

patch 8.2.0920: writing viminfo fails with a circular reference

Problem:    Writing viminfo fails with a circular reference.
Solution:   Use copyID to detect the cycle. (closes #6217)
This commit is contained in:
Bram Moolenaar
2020-06-07 16:08:08 +02:00
parent 673fc3e23f
commit 5b157fe2ed
3 changed files with 52 additions and 2 deletions

View File

@@ -91,6 +91,28 @@ func Test_global_vars()
set viminfo-=!
endfunc
func Test_global_vars_with_circular_reference()
let g:MY_GLOBAL_LIST = []
call add(g:MY_GLOBAL_LIST, g:MY_GLOBAL_LIST)
let g:MY_GLOBAL_DICT = {}
let g:MY_GLOBAL_DICT['self'] = g:MY_GLOBAL_DICT
set viminfo='100,<50,s10,h,!,nviminfo
wv! Xviminfo
call assert_equal(v:errmsg, '')
unlet g:MY_GLOBAL_LIST
unlet g:MY_GLOBAL_DICT
rv! Xviminfo
call assert_equal(v:errmsg, '')
call assert_true(!exists('g:MY_GLOBAL_LIST'))
call assert_true(!exists('g:MY_GLOBAL_DICT'))
call delete('Xviminfo')
set viminfo-=!
endfunc
func Test_cmdline_history()
call histdel(':')
call test_settime(11)

View File

@@ -754,6 +754,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
920,
/**/
919,
/**/

View File

@@ -1337,8 +1337,34 @@ write_viminfo_varlist(FILE *fp)
case VAR_STRING: s = "STR"; break;
case VAR_NUMBER: s = "NUM"; break;
case VAR_FLOAT: s = "FLO"; break;
case VAR_DICT: s = "DIC"; break;
case VAR_LIST: s = "LIS"; break;
case VAR_DICT:
{
dict_T *di = this_var->di_tv.vval.v_dict;
int copyID = get_copyID();
s = "DIC";
if (di != NULL && !set_ref_in_ht(
&di->dv_hashtab, copyID, NULL)
&& di->dv_copyID == copyID)
// has a circular reference, can't turn the
// value into a string
continue;
break;
}
case VAR_LIST:
{
list_T *l = this_var->di_tv.vval.v_list;
int copyID = get_copyID();
s = "LIS";
if (l != NULL && !set_ref_in_list_items(
l, copyID, NULL)
&& l->lv_copyID == copyID)
// has a circular reference, can't turn the
// value into a string
continue;
break;
}
case VAR_BLOB: s = "BLO"; break;
case VAR_BOOL: s = "XPL"; break; // backwards compat.
case VAR_SPECIAL: s = "XPL"; break;