Skip to content

Commit 916a818

Browse files
committed
patch 8.1.0544: setting 'filetype' in a modeline causes an error
Problem: Setting 'filetype' in a modeline causes an error (Hirohito Higashi). Solution: Don't add the P_INSECURE flag when setting 'filetype' from a modeline. Also for 'syntax'.
1 parent 4e303c8 commit 916a818

3 files changed

Lines changed: 140 additions & 22 deletions

File tree

src/option.c

Lines changed: 62 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -3284,7 +3284,7 @@ static char *(p_scl_values[]) = {"yes", "no", "auto", NULL};
32843284
static void set_options_default(int opt_flags);
32853285
static void set_string_default_esc(char *name, char_u *val, int escape);
32863286
static char_u *term_bg_default(void);
3287-
static void did_set_option(int opt_idx, int opt_flags, int new_value);
3287+
static void did_set_option(int opt_idx, int opt_flags, int new_value, int value_checked);
32883288
static char_u *option_expand(int opt_idx, char_u *val);
32893289
static void didset_options(void);
32903290
static void didset_options2(void);
@@ -3295,7 +3295,7 @@ static long_u *insecure_flag(int opt_idx, int opt_flags);
32953295
# define insecure_flag(opt_idx, opt_flags) (&options[opt_idx].flags)
32963296
#endif
32973297
static void set_string_option_global(int opt_idx, char_u **varp);
3298-
static char_u *did_set_string_option(int opt_idx, char_u **varp, int new_value_alloced, char_u *oldval, char_u *errbuf, int opt_flags);
3298+
static char_u *did_set_string_option(int opt_idx, char_u **varp, int new_value_alloced, char_u *oldval, char_u *errbuf, int opt_flags, int *value_checked);
32993299
static char_u *set_chars_option(char_u **varp);
33003300
#ifdef FEAT_CLIPBOARD
33013301
static char_u *check_clipboard_option(void);
@@ -4706,6 +4706,7 @@ do_set(
47064706
else
47074707
{
47084708
int value_is_replaced = !prepending && !adding && !removing;
4709+
int value_checked = FALSE;
47094710

47104711
if (flags & P_BOOL) /* boolean */
47114712
{
@@ -5236,7 +5237,8 @@ do_set(
52365237
// or 'filetype' autocommands may be triggered that can
52375238
// cause havoc.
52385239
errmsg = did_set_string_option(opt_idx, (char_u **)varp,
5239-
new_value_alloced, oldval, errbuf, opt_flags);
5240+
new_value_alloced, oldval, errbuf,
5241+
opt_flags, &value_checked);
52405242

52415243
if (did_inc_secure)
52425244
--secure;
@@ -5280,7 +5282,8 @@ do_set(
52805282
}
52815283

52825284
if (opt_idx >= 0)
5283-
did_set_option(opt_idx, opt_flags, value_is_replaced);
5285+
did_set_option(
5286+
opt_idx, opt_flags, value_is_replaced, value_checked);
52845287
}
52855288

52865289
skip:
@@ -5348,8 +5351,10 @@ do_set(
53485351
static void
53495352
did_set_option(
53505353
int opt_idx,
5351-
int opt_flags, /* possibly with OPT_MODELINE */
5352-
int new_value) /* value was replaced completely */
5354+
int opt_flags, // possibly with OPT_MODELINE
5355+
int new_value, // value was replaced completely
5356+
int value_checked) // value was checked to be safe, no need to set the
5357+
// P_INSECURE flag.
53535358
{
53545359
long_u *p;
53555360

@@ -5359,11 +5364,11 @@ did_set_option(
53595364
* set the P_INSECURE flag. Otherwise, if a new value is stored reset the
53605365
* flag. */
53615366
p = insecure_flag(opt_idx, opt_flags);
5362-
if (secure
5367+
if (!value_checked && (secure
53635368
#ifdef HAVE_SANDBOX
53645369
|| sandbox != 0
53655370
#endif
5366-
|| (opt_flags & OPT_MODELINE))
5371+
|| (opt_flags & OPT_MODELINE)))
53675372
*p = *p | P_INSECURE;
53685373
else if (new_value)
53695374
*p = *p & ~P_INSECURE;
@@ -6036,6 +6041,7 @@ set_string_option(
60366041
char_u *saved_newval = NULL;
60376042
#endif
60386043
char_u *r = NULL;
6044+
int value_checked = FALSE;
60396045

60406046
if (options[opt_idx].var == NULL) /* don't set hidden option */
60416047
return NULL;
@@ -6063,8 +6069,8 @@ set_string_option(
60636069
}
60646070
#endif
60656071
if ((r = did_set_string_option(opt_idx, varp, TRUE, oldval, NULL,
6066-
opt_flags)) == NULL)
6067-
did_set_option(opt_idx, opt_flags, TRUE);
6072+
opt_flags, &value_checked)) == NULL)
6073+
did_set_option(opt_idx, opt_flags, TRUE, value_checked);
60686074

60696075
#if defined(FEAT_EVAL)
60706076
/* call autocommand after handling side effects */
@@ -6099,12 +6105,14 @@ valid_filetype(char_u *val)
60996105
*/
61006106
static char_u *
61016107
did_set_string_option(
6102-
int opt_idx, /* index in options[] table */
6103-
char_u **varp, /* pointer to the option variable */
6104-
int new_value_alloced, /* new value was allocated */
6105-
char_u *oldval, /* previous value of the option */
6106-
char_u *errbuf, /* buffer for errors, or NULL */
6107-
int opt_flags) /* OPT_LOCAL and/or OPT_GLOBAL */
6108+
int opt_idx, // index in options[] table
6109+
char_u **varp, // pointer to the option variable
6110+
int new_value_alloced, // new value was allocated
6111+
char_u *oldval, // previous value of the option
6112+
char_u *errbuf, // buffer for errors, or NULL
6113+
int opt_flags, // OPT_LOCAL and/or OPT_GLOBAL
6114+
int *value_checked) // value was checked to be save, no
6115+
// need to set P_INSECURE
61086116
{
61096117
char_u *errmsg = NULL;
61106118
char_u *s, *p;
@@ -6134,10 +6142,9 @@ did_set_string_option(
61346142
errmsg = e_secure;
61356143
}
61366144

6137-
/* Check for a "normal" directory or file name in some options. Disallow a
6138-
* path separator (slash and/or backslash), wildcards and characters that
6139-
* are often illegal in a file name. Be more permissive if "secure" is off.
6140-
*/
6145+
// Check for a "normal" directory or file name in some options. Disallow a
6146+
// path separator (slash and/or backslash), wildcards and characters that
6147+
// are often illegal in a file name. Be more permissive if "secure" is off.
61416148
else if (((options[opt_idx].flags & P_NFNAME)
61426149
&& vim_strpbrk(*varp, (char_u *)(secure
61436150
? "/\\*?[|;&<>\r\n" : "/\\*?[<>\r\n")) != NULL)
@@ -6524,9 +6531,23 @@ did_set_string_option(
65246531
if (!valid_filetype(*varp))
65256532
errmsg = e_invarg;
65266533
else
6527-
/* load or unload key mapping tables */
6534+
{
6535+
int secure_save = secure;
6536+
6537+
// Reset the secure flag, since the value of 'keymap' has
6538+
// been checked to be safe.
6539+
secure = 0;
6540+
6541+
// load or unload key mapping tables
65286542
errmsg = keymap_init();
65296543

6544+
secure = secure_save;
6545+
6546+
// Since we check the value, there is no need to set P_INSECURE,
6547+
// even when the value comes from a modeline.
6548+
*value_checked = TRUE;
6549+
}
6550+
65306551
if (errmsg == NULL)
65316552
{
65326553
if (*curbuf->b_p_keymap != NUL)
@@ -7523,7 +7544,13 @@ did_set_string_option(
75237544
if (!valid_filetype(*varp))
75247545
errmsg = e_invarg;
75257546
else
7547+
{
75267548
value_changed = STRCMP(oldval, *varp) != 0;
7549+
7550+
// Since we check the value, there is no need to set P_INSECURE,
7551+
// even when the value comes from a modeline.
7552+
*value_checked = TRUE;
7553+
}
75277554
}
75287555

75297556
#ifdef FEAT_SYN_HL
@@ -7532,7 +7559,13 @@ did_set_string_option(
75327559
if (!valid_filetype(*varp))
75337560
errmsg = e_invarg;
75347561
else
7562+
{
75357563
value_changed = STRCMP(oldval, *varp) != 0;
7564+
7565+
// Since we check the value, there is no need to set P_INSECURE,
7566+
// even when the value comes from a modeline.
7567+
*value_checked = TRUE;
7568+
}
75367569
}
75377570
#endif
75387571

@@ -7752,7 +7785,12 @@ did_set_string_option(
77527785
* already set to this value. */
77537786
if (!(opt_flags & OPT_MODELINE) || value_changed)
77547787
{
7755-
static int ft_recursive = 0;
7788+
static int ft_recursive = 0;
7789+
int secure_save = secure;
7790+
7791+
// Reset the secure flag, since the value of 'filetype' has
7792+
// been checked to be safe.
7793+
secure = 0;
77567794

77577795
++ft_recursive;
77587796
did_filetype = TRUE;
@@ -7764,6 +7802,8 @@ did_set_string_option(
77647802
/* Just in case the old "curbuf" is now invalid. */
77657803
if (varp != &(curbuf->b_p_ft))
77667804
varp = NULL;
7805+
7806+
secure = secure_save;
77677807
}
77687808
}
77697809
#ifdef FEAT_SPELL

src/testdir/test_modeline.vim

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,83 @@ func Test_modeline_invalid()
66
let modeline = &modeline
77
set modeline
88
call assert_fails('split Xmodeline', 'E518:')
9+
910
let &modeline = modeline
1011
bwipe!
1112
call delete('Xmodeline')
1213
endfunc
14+
15+
func Test_modeline_filetype()
16+
call writefile(['vim: set ft=c :', 'nothing'], 'Xmodeline_filetype')
17+
let modeline = &modeline
18+
set modeline
19+
filetype plugin on
20+
split Xmodeline_filetype
21+
call assert_equal("c", &filetype)
22+
call assert_equal(1, b:did_ftplugin)
23+
call assert_equal("ccomplete#Complete", &ofu)
24+
25+
bwipe!
26+
call delete('Xmodeline_filetype')
27+
let &modeline = modeline
28+
filetype plugin off
29+
endfunc
30+
31+
func Test_modeline_syntax()
32+
call writefile(['vim: set syn=c :', 'nothing'], 'Xmodeline_syntax')
33+
let modeline = &modeline
34+
set modeline
35+
syntax enable
36+
split Xmodeline_syntax
37+
call assert_equal("c", &syntax)
38+
call assert_equal("c", b:current_syntax)
39+
40+
bwipe!
41+
call delete('Xmodeline_syntax')
42+
let &modeline = modeline
43+
syntax off
44+
endfunc
45+
46+
func Test_modeline_keymap()
47+
call writefile(['vim: set keymap=greek :', 'nothing'], 'Xmodeline_keymap')
48+
let modeline = &modeline
49+
set modeline
50+
split Xmodeline_keymap
51+
call assert_equal("greek", &keymap)
52+
call assert_match('greek\|grk', b:keymap_name)
53+
54+
bwipe!
55+
call delete('Xmodeline_keymap')
56+
let &modeline = modeline
57+
set keymap= iminsert=0 imsearch=-1
58+
endfunc
59+
60+
func s:modeline_fails(what, text)
61+
let fname = "Xmodeline_fails_" . a:what
62+
call writefile(['vim: set ' . a:text . ' :', 'nothing'], fname)
63+
let modeline = &modeline
64+
set modeline
65+
filetype plugin on
66+
syntax enable
67+
call assert_fails('split ' . fname, 'E474:')
68+
call assert_equal("", &filetype)
69+
call assert_equal("", &syntax)
70+
71+
bwipe!
72+
call delete(fname)
73+
let &modeline = modeline
74+
filetype plugin off
75+
syntax off
76+
endfunc
77+
78+
func Test_modeline_filetype_fails()
79+
call s:modeline_fails('filetype', 'ft=evil$CMD')
80+
endfunc
81+
82+
func Test_modeline_syntax_fails()
83+
call s:modeline_fails('syntax', 'syn=evil$CMD')
84+
endfunc
85+
86+
func Test_modeline_keymap_fails()
87+
call s:modeline_fails('keymap', 'keymap=evil$CMD')
88+
endfunc

src/version.c

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

793793
static int included_patches[] =
794794
{ /* Add new patch number below this line */
795+
/**/
796+
544,
795797
/**/
796798
543,
797799
/**/

0 commit comments

Comments
 (0)