Skip to content

Commit 24c77a1

Browse files
committed
patch 7.4.1644
Problem: Using string() on a partial that exists in the dictionary it binds results in an error. (Nikolai Pavlov) Solution: Make string() not fail on a recursively nested structure. (Ken Takta)
1 parent d4caf5c commit 24c77a1

3 files changed

Lines changed: 62 additions & 49 deletions

File tree

src/eval.c

Lines changed: 47 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -7851,10 +7851,50 @@ echo_string(
78517851
break;
78527852

78537853
case VAR_PARTIAL:
7854-
*tofree = NULL;
7855-
/* TODO: arguments */
7856-
r = tv->vval.v_partial == NULL ? NULL : tv->vval.v_partial->pt_name;
7857-
break;
7854+
{
7855+
partial_T *pt = tv->vval.v_partial;
7856+
char_u *fname = string_quote(pt == NULL ? NULL
7857+
: pt->pt_name, FALSE);
7858+
garray_T ga;
7859+
int i;
7860+
char_u *tf;
7861+
7862+
ga_init2(&ga, 1, 100);
7863+
ga_concat(&ga, (char_u *)"function(");
7864+
if (fname != NULL)
7865+
{
7866+
ga_concat(&ga, fname);
7867+
vim_free(fname);
7868+
}
7869+
if (pt != NULL && pt->pt_argc > 0)
7870+
{
7871+
ga_concat(&ga, (char_u *)", [");
7872+
for (i = 0; i < pt->pt_argc; ++i)
7873+
{
7874+
if (i > 0)
7875+
ga_concat(&ga, (char_u *)", ");
7876+
ga_concat(&ga,
7877+
tv2string(&pt->pt_argv[i], &tf, numbuf, copyID));
7878+
vim_free(tf);
7879+
}
7880+
ga_concat(&ga, (char_u *)"]");
7881+
}
7882+
if (pt != NULL && pt->pt_dict != NULL)
7883+
{
7884+
typval_T dtv;
7885+
7886+
ga_concat(&ga, (char_u *)", ");
7887+
dtv.v_type = VAR_DICT;
7888+
dtv.vval.v_dict = pt->pt_dict;
7889+
ga_concat(&ga, tv2string(&dtv, &tf, numbuf, copyID));
7890+
vim_free(tf);
7891+
}
7892+
ga_concat(&ga, (char_u *)")");
7893+
7894+
*tofree = ga.ga_data;
7895+
r = *tofree;
7896+
break;
7897+
}
78587898

78597899
case VAR_LIST:
78607900
if (tv->vval.v_list == NULL)
@@ -7941,50 +7981,6 @@ tv2string(
79417981
case VAR_FUNC:
79427982
*tofree = string_quote(tv->vval.v_string, TRUE);
79437983
return *tofree;
7944-
case VAR_PARTIAL:
7945-
{
7946-
partial_T *pt = tv->vval.v_partial;
7947-
char_u *fname = string_quote(pt == NULL ? NULL
7948-
: pt->pt_name, FALSE);
7949-
garray_T ga;
7950-
int i;
7951-
char_u *tf;
7952-
7953-
ga_init2(&ga, 1, 100);
7954-
ga_concat(&ga, (char_u *)"function(");
7955-
if (fname != NULL)
7956-
{
7957-
ga_concat(&ga, fname);
7958-
vim_free(fname);
7959-
}
7960-
if (pt != NULL && pt->pt_argc > 0)
7961-
{
7962-
ga_concat(&ga, (char_u *)", [");
7963-
for (i = 0; i < pt->pt_argc; ++i)
7964-
{
7965-
if (i > 0)
7966-
ga_concat(&ga, (char_u *)", ");
7967-
ga_concat(&ga,
7968-
tv2string(&pt->pt_argv[i], &tf, numbuf, copyID));
7969-
vim_free(tf);
7970-
}
7971-
ga_concat(&ga, (char_u *)"]");
7972-
}
7973-
if (pt != NULL && pt->pt_dict != NULL)
7974-
{
7975-
typval_T dtv;
7976-
7977-
ga_concat(&ga, (char_u *)", ");
7978-
dtv.v_type = VAR_DICT;
7979-
dtv.vval.v_dict = pt->pt_dict;
7980-
ga_concat(&ga, tv2string(&dtv, &tf, numbuf, copyID));
7981-
vim_free(tf);
7982-
}
7983-
ga_concat(&ga, (char_u *)")");
7984-
7985-
*tofree = ga.ga_data;
7986-
return *tofree;
7987-
}
79887984
case VAR_STRING:
79897985
*tofree = string_quote(tv->vval.v_string, FALSE);
79907986
return *tofree;
@@ -7997,6 +7993,7 @@ tv2string(
79977993
case VAR_NUMBER:
79987994
case VAR_LIST:
79997995
case VAR_DICT:
7996+
case VAR_PARTIAL:
80007997
case VAR_SPECIAL:
80017998
case VAR_JOB:
80027999
case VAR_CHANNEL:
@@ -19258,7 +19255,8 @@ f_string(typval_T *argvars, typval_T *rettv)
1925819255
char_u numbuf[NUMBUFLEN];
1925919256

1926019257
rettv->v_type = VAR_STRING;
19261-
rettv->vval.v_string = tv2string(&argvars[0], &tofree, numbuf, 0);
19258+
rettv->vval.v_string = tv2string(&argvars[0], &tofree, numbuf,
19259+
get_copyID());
1926219260
/* Make a copy if we have a value but it's not in allocated memory. */
1926319261
if (rettv->vval.v_string != NULL && tofree == NULL)
1926419262
rettv->vval.v_string = vim_strsave(rettv->vval.v_string);

src/testdir/test_partial.vim

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,3 +180,16 @@ func Test_func_unref()
180180
unlet obj
181181
call assert_false(exists('*{' . funcnumber . '}'))
182182
endfunc
183+
184+
func Test_tostring()
185+
let d = {}
186+
let d.d = d
187+
function d.test3()
188+
echo 42
189+
endfunction
190+
try
191+
call string(d.test3)
192+
catch
193+
call assert_true(v:false, v:exception)
194+
endtry
195+
endfunc

src/version.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -748,6 +748,8 @@ static char *(features[]) =
748748

749749
static int included_patches[] =
750750
{ /* Add new patch number below this line */
751+
/**/
752+
1644,
751753
/**/
752754
1643,
753755
/**/

0 commit comments

Comments
 (0)