Skip to content

Commit ed18f2c

Browse files
committed
patch 8.1.0814: :mksession cannot handle a very long 'runtimepath'
Problem: :mksession cannot handle a very long 'runtimepath'. (Timothy Madden) Solution: Expand each part separately, instead of the whole option at once. (Christian Brabandt, closes #3466)
1 parent 0566e89 commit ed18f2c

3 files changed

Lines changed: 78 additions & 13 deletions

File tree

src/option.c

Lines changed: 52 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3243,7 +3243,7 @@ static int find_key_option(char_u *arg_arg, int has_lt);
32433243
static void showoptions(int all, int opt_flags);
32443244
static int optval_default(struct vimoption *, char_u *varp);
32453245
static void showoneopt(struct vimoption *, int opt_flags);
3246-
static int put_setstring(FILE *fd, char *cmd, char *name, char_u **valuep, int expand);
3246+
static int put_setstring(FILE *fd, char *cmd, char *name, char_u **valuep, long_u flags);
32473247
static int put_setnum(FILE *fd, char *cmd, char *name, long *valuep);
32483248
static int put_setbool(FILE *fd, char *cmd, char *name, int value);
32493249
static int istermoption(struct vimoption *);
@@ -10297,7 +10297,7 @@ makeset(FILE *fd, int opt_flags, int local_only)
1029710297
do_endif = TRUE;
1029810298
}
1029910299
if (put_setstring(fd, cmd, p->fullname, (char_u **)varp,
10300-
(p->flags & P_EXPAND) != 0) == FAIL)
10300+
p->flags) == FAIL)
1030110301
return FAIL;
1030210302
if (do_endif)
1030310303
{
@@ -10319,14 +10319,14 @@ makeset(FILE *fd, int opt_flags, int local_only)
1031910319
int
1032010320
makefoldset(FILE *fd)
1032110321
{
10322-
if (put_setstring(fd, "setlocal", "fdm", &curwin->w_p_fdm, FALSE) == FAIL
10322+
if (put_setstring(fd, "setlocal", "fdm", &curwin->w_p_fdm, 0) == FAIL
1032310323
# ifdef FEAT_EVAL
10324-
|| put_setstring(fd, "setlocal", "fde", &curwin->w_p_fde, FALSE)
10324+
|| put_setstring(fd, "setlocal", "fde", &curwin->w_p_fde, 0)
1032510325
== FAIL
1032610326
# endif
10327-
|| put_setstring(fd, "setlocal", "fmr", &curwin->w_p_fmr, FALSE)
10327+
|| put_setstring(fd, "setlocal", "fmr", &curwin->w_p_fmr, 0)
1032810328
== FAIL
10329-
|| put_setstring(fd, "setlocal", "fdi", &curwin->w_p_fdi, FALSE)
10329+
|| put_setstring(fd, "setlocal", "fdi", &curwin->w_p_fdi, 0)
1033010330
== FAIL
1033110331
|| put_setnum(fd, "setlocal", "fdl", &curwin->w_p_fdl) == FAIL
1033210332
|| put_setnum(fd, "setlocal", "fml", &curwin->w_p_fml) == FAIL
@@ -10345,10 +10345,12 @@ put_setstring(
1034510345
char *cmd,
1034610346
char *name,
1034710347
char_u **valuep,
10348-
int expand)
10348+
long_u flags)
1034910349
{
1035010350
char_u *s;
10351-
char_u *buf;
10351+
char_u *buf = NULL;
10352+
char_u *part = NULL;
10353+
char_u *p;
1035210354

1035310355
if (fprintf(fd, "%s %s=", cmd, name) < 0)
1035410356
return FAIL;
@@ -10364,12 +10366,46 @@ put_setstring(
1036410366
if (put_escstr(fd, str2special(&s, FALSE), 2) == FAIL)
1036510367
return FAIL;
1036610368
}
10367-
else if (expand)
10369+
// expand the option value, replace $HOME by ~
10370+
else if ((flags & P_EXPAND) != 0)
1036810371
{
10369-
buf = alloc(MAXPATHL);
10372+
int size = (int)STRLEN(*valuep) + 1;
10373+
10374+
// replace home directory in the whole option value into "buf"
10375+
buf = alloc(size);
1037010376
if (buf == NULL)
10371-
return FAIL;
10372-
home_replace(NULL, *valuep, buf, MAXPATHL, FALSE);
10377+
goto fail;
10378+
home_replace(NULL, *valuep, buf, size, FALSE);
10379+
10380+
// If the option value is longer than MAXPATHL, we need to append
10381+
// earch comma separated part of the option separately, so that it
10382+
// can be expanded when read back.
10383+
if (size >= MAXPATHL && (flags & P_COMMA) != 0
10384+
&& vim_strchr(*valuep, ',') != NULL)
10385+
{
10386+
part = alloc(size);
10387+
if (part == NULL)
10388+
goto fail;
10389+
10390+
// write line break to clear the option, e.g. ':set rtp='
10391+
if (put_eol(fd) == FAIL)
10392+
goto fail;
10393+
10394+
p = buf;
10395+
while (*p != NUL)
10396+
{
10397+
// for each comma separated option part, append value to
10398+
// the option, :set rtp+=value
10399+
if (fprintf(fd, "%s %s+=", cmd, name) < 0)
10400+
goto fail;
10401+
(void)copy_option_part(&p, part, size, ",");
10402+
if (put_escstr(fd, part, 2) == FAIL || put_eol(fd) == FAIL)
10403+
goto fail;
10404+
}
10405+
vim_free(buf);
10406+
vim_free(part);
10407+
return OK;
10408+
}
1037310409
if (put_escstr(fd, buf, 2) == FAIL)
1037410410
{
1037510411
vim_free(buf);
@@ -10383,6 +10419,10 @@ put_setstring(
1038310419
if (put_eol(fd) < 0)
1038410420
return FAIL;
1038510421
return OK;
10422+
fail:
10423+
vim_free(buf);
10424+
vim_free(part);
10425+
return FAIL;
1038610426
}
1038710427

1038810428
static int

src/testdir/test_mksession.vim

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
set encoding=latin1
44
scriptencoding latin1
55

6-
if !has('multi_byte') || !has('mksession')
6+
if !has('mksession')
77
finish
88
endif
99

@@ -126,6 +126,29 @@ func Test_mksession_large_winheight()
126126
call delete('Xtest_mks_winheight.out')
127127
endfunc
128128

129+
func Test_mksession_rtp()
130+
new
131+
let _rtp=&rtp
132+
" Make a real long (invalid) runtimepath value,
133+
" that should exceed PATH_MAX (hopefully)
134+
let newrtp=&rtp.',~'.repeat('/foobar', 1000)
135+
let newrtp.=",".expand("$HOME")."/.vim"
136+
let &rtp=newrtp
137+
138+
" determine expected value
139+
let expected=split(&rtp, ',')
140+
let expected = map(expected, '"set runtimepath+=".v:val')
141+
let expected = ['set runtimepath='] + expected
142+
let expected = map(expected, {v,w -> substitute(w, $HOME, "~", "g")})
143+
144+
mksession! Xtest_mks.out
145+
let &rtp=_rtp
146+
let li = filter(readfile('Xtest_mks.out'), 'v:val =~# "runtimepath"')
147+
call assert_equal(expected, li)
148+
149+
call delete('Xtest_mks.out')
150+
endfunc
151+
129152
func Test_mksession_arglist()
130153
argdel *
131154
next file1 file2 file3 file4

src/version.c

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

788788
static int included_patches[] =
789789
{ /* Add new patch number below this line */
790+
/**/
791+
84,
790792
/**/
791793
813,
792794
/**/

0 commit comments

Comments
 (0)