patch 9.2.0499: modeline: allow to disable modelines with modelinestrict

Problem:  Cannot disable modeline processing when loading a file
          (Mao-Yining, after v9.2.0350)
Solution: Allow to disable modeline processing even when
          'modelienstrict' is in effect.

fixes:  #20103
closes: #20229

Signed-off-by: Christian Brabandt <cb@256bit.org>
Signed-off-by: Christian Brabandt <cb@256bit.org>
This commit is contained in:
Christian Brabandt
2026-05-18 18:59:03 +00:00
parent c920d93443
commit 4397227119
4 changed files with 75 additions and 6 deletions
+6 -1
View File
@@ -1,4 +1,4 @@
*options.txt* For Vim version 9.2. Last change: 2026 May 17
*options.txt* For Vim version 9.2. Last change: 2026 May 18
VIM REFERENCE MANUAL by Bram Moolenaar
@@ -6239,6 +6239,11 @@ A jump table for the options with a short description can be found at |Q_op|.
This option cannot be set from a |modeline| or in the |sandbox|, for
security reasons.
As an exception, `set nomodeline` is honored from within a modeline
even when 'modelinestrict' is on. Other forms (`set modeline=0`,
`set modeline!`, `set invmodeline`) are still silently ignored.
This lets a file disable further modeline processing for itself.
The behaviour of 'modeline', 'modelinestrict' and 'modelineexpr' is
as follows:
+15 -5
View File
@@ -1589,7 +1589,12 @@ is_modeline_whitelisted(char *name)
* if it can be changed.
*/
static int
validate_opt_idx(int opt_idx, int opt_flags, long_u flags, char **errmsg)
validate_opt_idx(
int opt_idx,
int opt_flags,
long_u flags,
char **errmsg,
set_prefix_T prefix)
{
// Skip all options that are not window-local (used when showing
// an already loaded buffer in a window).
@@ -1617,9 +1622,14 @@ validate_opt_idx(int opt_idx, int opt_flags, long_u flags, char **errmsg)
}
// When 'modelinestrict' is on, only whitelisted options may be
// set from a modeline. Silently skip others.
if (p_mlstr && opt_idx >= 0
&& !is_modeline_whitelisted(options[opt_idx].fullname))
return FAIL;
if (p_mlstr && opt_idx >= 0)
{
// special case: allow disabling modeline
if (options[opt_idx].indir == PV_ML && prefix == PREFIX_NO)
return OK;
else if (!is_modeline_whitelisted(options[opt_idx].fullname))
return FAIL;
}
#ifdef FEAT_DIFF
// In diff mode some options are overruled. This avoids that
// 'foldmethod' becomes "marker" instead of "diff" and that
@@ -2864,7 +2874,7 @@ do_set_option(
}
// Make sure the option value can be changed.
if (validate_opt_idx(opt_idx, opt_flags, flags, &errmsg) == FAIL)
if (validate_opt_idx(opt_idx, opt_flags, flags, &errmsg, prefix) == FAIL)
goto skip;
int cp_val = p_cp;
+52
View File
@@ -666,4 +666,56 @@ func Test_modeline_strict_cannot_be_set_from_modeline()
let &modeline = modeline
endfunc
func Test_modeline_nomodeline_with_modelinestrict()
let modeline = &modeline
let modelinestrict = &modelinestrict
let modelines = &modelines
set modelinestrict modeline modelines=5
let ml_before = &g:modeline
call writefile(['# vim: set nomodeline:', 'line2'], 'Xnoml', 'D')
split Xnoml
call assert_equal(0, &l:modeline, 'b_p_ml should be off')
call assert_equal(ml_before, &g:modeline, 'global p_ml must not change')
bwipe!
" A fresh buffer must still inherit the unchanged global default
new
call assert_equal(ml_before, &l:modeline,
\ 'new buffer should inherit unchanged global')
bwipe!
let &modeline = modeline
let &modelinestrict = modelinestrict
let &modelines = modelines
endfunc
func Test_modeline_nomodeline_skips_trailing_modelines()
let modeline = &modeline
let modelinestrict = &modelinestrict
let ts_save = &ts
set modeline modelinestrict ts=8
" Line 1 disables modelines; the trailing modeline must therefore
" never execute even though 'tabstop' is whitelisted.
call writefile([
\ '# vim: set nomodeline :',
\ 'middle line 1',
\ 'middle line 2',
\ 'middle line 3',
\ '# vim: set ts=99 :',
\ ], 'Xmodeline_disable_top', 'D')
split Xmodeline_disable_top
call assert_equal(0, &l:modeline,
\ 'top modeline must have disabled b_p_ml')
call assert_equal(8, &ts,
\ 'trailing modeline must not have run after nomodeline')
bwipe!
let &modeline = modeline
let &modelinestrict = modelinestrict
let &ts = ts_save
endfunc
" vim: shiftwidth=2 sts=2 expandtab
+2
View File
@@ -729,6 +729,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
499,
/**/
498,
/**/