patch 9.2.0499: modeline: allow to disable modelines with modelinestrict

Commit: 
https://github.com/vim/vim/commit/4397227119e3ebaa879552dcbcb18338d18f4850
Author: Christian Brabandt <[email protected]>
Date:   Mon May 18 18:59:03 2026 +0000

    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 <[email protected]>
    Signed-off-by: Christian Brabandt <[email protected]>

diff --git a/runtime/doc/options.txt b/runtime/doc/options.txt
index 2ba59824f..b7d74e9f8 100644
--- a/runtime/doc/options.txt
+++ b/runtime/doc/options.txt
@@ -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:
 
diff --git a/src/option.c b/src/option.c
index 31f84c98d..d15cc3f3c 100644
--- a/src/option.c
+++ b/src/option.c
@@ -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;
diff --git a/src/testdir/test_modeline.vim b/src/testdir/test_modeline.vim
index cb489ee15..c436cbc27 100644
--- a/src/testdir/test_modeline.vim
+++ b/src/testdir/test_modeline.vim
@@ -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
diff --git a/src/version.c b/src/version.c
index f348ffc9e..4ce617565 100644
--- a/src/version.c
+++ b/src/version.c
@@ -729,6 +729,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    499,
 /**/
     498,
 /**/

-- 
-- 
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php

--- 
You received this message because you are subscribed to the Google Groups 
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion visit 
https://groups.google.com/d/msgid/vim_dev/E1wP3Qg-00BiPp-QB%40256bit.org.

Raspunde prin e-mail lui