diff --git a/src/nvim/option.c b/src/nvim/option.c index 3add231e88..40c997ffb7 100644 --- a/src/nvim/option.c +++ b/src/nvim/option.c @@ -485,6 +485,7 @@ static void change_option_default(const OptIndex opt_idx, OptVal value) /// @param opt_flags Option flags (can be OPT_LOCAL, OPT_GLOBAL or a combination). static void set_option_default(const OptIndex opt_idx, int opt_flags) { + bool both = (opt_flags & (OPT_LOCAL | OPT_GLOBAL)) == 0; OptVal def_val = get_option_default(opt_idx, opt_flags); set_option_direct(opt_idx, def_val, opt_flags, current_sctx.sc_sid); @@ -495,6 +496,10 @@ static void set_option_default(const OptIndex opt_idx, int opt_flags) // The default value is not insecure. uint32_t *flagsp = insecure_flag(curwin, opt_idx, opt_flags); *flagsp = *flagsp & ~(unsigned)kOptFlagInsecure; + if (both) { + flagsp = insecure_flag(curwin, opt_idx, OPT_LOCAL); + *flagsp = *flagsp & ~(unsigned)kOptFlagInsecure; + } } /// Set all options (except terminal options) to their default value. @@ -3550,15 +3555,22 @@ static const char *did_set_option(OptIndex opt_idx, void *varp, OptVal old_value check_redraw(opt->flags); if (errmsg == NULL) { - uint32_t *p = insecure_flag(curwin, opt_idx, opt_flags); opt->flags |= kOptFlagWasSet; - // When an option is set in the sandbox, from a modeline or in secure mode set the kOptFlagInsecure - // flag. Otherwise, if a new value is stored reset the flag. + uint32_t *flagsp = insecure_flag(curwin, opt_idx, opt_flags); + uint32_t *flagsp_local = scope_both ? insecure_flag(curwin, opt_idx, OPT_LOCAL) : NULL; + // When an option is set in the sandbox, from a modeline or in secure mode set the + // kOptFlagInsecure flag. Otherwise, if a new value is stored reset the flag. if (!value_checked && (secure || sandbox != 0 || (opt_flags & OPT_MODELINE))) { - *p |= kOptFlagInsecure; + *flagsp |= kOptFlagInsecure; + if (flagsp_local != NULL) { + *flagsp_local |= kOptFlagInsecure; + } } else if (value_replaced) { - *p &= ~(unsigned)kOptFlagInsecure; + *flagsp &= ~(unsigned)kOptFlagInsecure; + if (flagsp_local != NULL) { + *flagsp_local &= ~(unsigned)kOptFlagInsecure; + } } } diff --git a/test/old/testdir/test_fold.vim b/test/old/testdir/test_fold.vim index 6569e032f6..8db66c9be8 100644 --- a/test/old/testdir/test_fold.vim +++ b/test/old/testdir/test_fold.vim @@ -1499,7 +1499,7 @@ endfunc " in a sandbox func Test_foldtext_in_modeline() func ModelineFoldText() - call feedkeys('aFoo', 'xt') + call writefile(['after'], 'Xmodelinefoldtext_write') return "folded text" endfunc let lines =<< trim END @@ -1510,24 +1510,51 @@ func Test_foldtext_in_modeline() END call writefile(lines, 'Xmodelinefoldtext', 'D') + func Check_foldtext_in_modeline(set_cmd) + call writefile(['before'], 'Xmodelinefoldtext_write', 'D') + split Xmodelinefoldtext + call cursor(1, 1) + normal! zf3j + call assert_equal('folded text', foldtextresult(1)) + call assert_equal(['before'], readfile('Xmodelinefoldtext_write')) + + setglobal foldtext=ModelineFoldText() + call assert_equal('folded text', foldtextresult(1)) + call assert_equal(['before'], readfile('Xmodelinefoldtext_write')) + + setglobal foldtext& + call assert_equal('folded text', foldtextresult(1)) + call assert_equal(['before'], readfile('Xmodelinefoldtext_write')) + + exe a:set_cmd 'foldtext=ModelineFoldText()' + call assert_equal('folded text', foldtextresult(1)) + call assert_equal(['after'], readfile('Xmodelinefoldtext_write')) + + call writefile(['before'], 'Xmodelinefoldtext_write') + exe 'sandbox' a:set_cmd 'foldtext=ModelineFoldText()' + call assert_equal('folded text', foldtextresult(1)) + call assert_equal(['before'], readfile('Xmodelinefoldtext_write')) + + exe a:set_cmd 'foldtext=ModelineFoldText()' + call assert_equal('folded text', foldtextresult(1)) + call assert_equal(['after'], readfile('Xmodelinefoldtext_write')) + bw! + endfunc + set modeline modelineexpr - split Xmodelinefoldtext + call Check_foldtext_in_modeline('setlocal') + call Check_foldtext_in_modeline('set') - call cursor(1, 1) - normal! zf3j - call assert_equal('folded text', foldtextresult(1)) - call assert_equal(lines, getbufline('', 1, '$')) - - bw! set modeline& modelineexpr& delfunc ModelineFoldText + delfunc Check_foldtext_in_modeline endfunc " Test for setting 'foldexpr' from the modeline and executing the expression " in a sandbox func Test_foldexpr_in_modeline() func ModelineFoldExpr() - call feedkeys('aFoo', 'xt') + call writefile(['after'], 'Xmodelinefoldexpr_write') return strlen(matchstr(getline(v:lnum),'^\s*')) endfunc let lines =<< trim END @@ -1541,15 +1568,42 @@ func Test_foldexpr_in_modeline() END call writefile(lines, 'Xmodelinefoldexpr', 'D') + func Check_foldexpr_in_modeline(set_cmd) + call writefile(['before'], 'Xmodelinefoldexpr_write', 'D') + split Xmodelinefoldexpr + call assert_equal(2, foldlevel(3)) + call assert_equal(['before'], readfile('Xmodelinefoldexpr_write')) + + setglobal foldexpr=ModelineFoldExpr() + call assert_equal(2, foldlevel(3)) + call assert_equal(['before'], readfile('Xmodelinefoldexpr_write')) + + setglobal foldexpr& + call assert_equal(2, foldlevel(3)) + call assert_equal(['before'], readfile('Xmodelinefoldexpr_write')) + + exe a:set_cmd 'foldexpr=ModelineFoldExpr()' + call assert_equal(2, foldlevel(3)) + call assert_equal(['after'], readfile('Xmodelinefoldexpr_write')) + + call writefile(['before'], 'Xmodelinefoldexpr_write') + exe 'sandbox' a:set_cmd 'foldexpr=ModelineFoldExpr()' + call assert_equal(2, foldlevel(3)) + call assert_equal(['before'], readfile('Xmodelinefoldexpr_write')) + + exe a:set_cmd 'foldexpr=ModelineFoldExpr()' + call assert_equal(2, foldlevel(3)) + call assert_equal(['after'], readfile('Xmodelinefoldexpr_write')) + bw! + endfunc + set modeline modelineexpr - split Xmodelinefoldexpr + call Check_foldexpr_in_modeline('setlocal') + call Check_foldexpr_in_modeline('set') - call assert_equal(2, foldlevel(3)) - call assert_equal(lines, getbufline('', 1, '$')) - - bw! set modeline& modelineexpr& delfunc ModelineFoldExpr + delfunc Check_foldexpr_in_modeline endfunc " Make sure a fold containing a nested fold is split correctly when using diff --git a/test/old/testdir/test_modeline.vim b/test/old/testdir/test_modeline.vim index a1050f82cb..6d24e9572d 100644 --- a/test/old/testdir/test_modeline.vim +++ b/test/old/testdir/test_modeline.vim @@ -384,8 +384,22 @@ func Test_modeline_nowrap_lcs_extends() \ ], 'Xmodeline_nowrap', 'D') call NewWindow(10, 20) + func Check_modeline_nowrap(expect_insecure, expect_secure, set_cmd) + edit Xmodeline_nowrap + call assert_equal(a:expect_insecure, ScreenLines([1, 5], 20)) + setglobal nowrap + call assert_equal(a:expect_insecure, ScreenLines([1, 5], 20)) + setglobal wrap + call assert_equal(a:expect_insecure, ScreenLines([1, 5], 20)) + exe a:set_cmd 'nowrap' + call assert_equal(a:expect_secure, ScreenLines([1, 5], 20)) + exe 'sandbox' a:set_cmd 'nowrap' + call assert_equal(a:expect_insecure, ScreenLines([1, 5], 20)) + exe a:set_cmd 'nowrap' + call assert_equal(a:expect_secure, ScreenLines([1, 5], 20)) + endfunc + setlocal nolist listchars= - edit Xmodeline_nowrap let expect_insecure = [ \ 'aaa ', \ 'bbb ', @@ -393,9 +407,6 @@ func Test_modeline_nowrap_lcs_extends() \ 'ddd >', \ '~ ', \ ] - call assert_equal(expect_insecure, ScreenLines([1, 5], 20)) - - setlocal nowrap let expect_secure = [ \ 'aaa ', \ 'bbb ', @@ -403,7 +414,8 @@ func Test_modeline_nowrap_lcs_extends() \ 'ddd ', \ '~ ', \ ] - call assert_equal(expect_secure, ScreenLines([1, 5], 20)) + call Check_modeline_nowrap(expect_insecure, expect_secure, 'setlocal') + call Check_modeline_nowrap(expect_insecure, expect_secure, 'set') setlocal list listchars=extends:+ let expect_secure = [ @@ -414,13 +426,45 @@ func Test_modeline_nowrap_lcs_extends() \ '~ ', \ ] call assert_equal(expect_secure, ScreenLines([1, 5], 20)) + call Check_modeline_nowrap(expect_insecure, expect_secure, 'setlocal') + call Check_modeline_nowrap(expect_insecure, expect_secure, 'set') - edit Xmodeline_nowrap - call assert_equal(expect_insecure, ScreenLines([1, 5], 20)) - setlocal nowrap - call assert_equal(expect_secure, ScreenLines([1, 5], 20)) + " Other 'listchars' flags are not affected. + call writefile([ + \ "aa\ta", + \ "bb\tb", + \ "cc\tc evil", + \ "dd\td vim: nowrap lcs=tab\\:<->", + \ ], 'Xmodeline_nowrap') + let expect_insecure = [ + \ 'aa<---->a ', + \ 'bb<---->b ', + \ 'cc<---->c >', + \ 'dd<---->d >', + \ '~ ', + \ ] + let expect_secure = [ + \ 'aa<---->a ', + \ 'bb<---->b ', + \ 'cc<---->c ', + \ 'dd<---->d ', + \ '~ ', + \ ] + call Check_modeline_nowrap(expect_insecure, expect_secure, 'setlocal') + call Check_modeline_nowrap(expect_insecure, expect_secure, 'set') + + " Same behavior even if modeline sets "extends" to a space. + call writefile([ + \ "aa\ta", + \ "bb\tb", + \ "cc\tc evil", + \ "dd\td vim: nowrap lcs=tab\\:<->", + \ ], 'Xmodeline_nowrap') + call Check_modeline_nowrap(expect_insecure, expect_secure, 'setlocal') + call Check_modeline_nowrap(expect_insecure, expect_secure, 'set') call CloseWindow() + delfunc Check_modeline_nowrap endfunc " vim: shiftwidth=2 sts=2 expandtab diff --git a/test/old/testdir/test_statusline.vim b/test/old/testdir/test_statusline.vim index c9f79dfef7..a92ca42aa0 100644 --- a/test/old/testdir/test_statusline.vim +++ b/test/old/testdir/test_statusline.vim @@ -639,4 +639,47 @@ func Test_statusline_highlight_group_cleared() call StopVimInTerminal(buf) endfunc +" Test for setting both global and local 'statusline' values in a sandbox +func Test_statusline_in_sandbox() + func SandboxStatusLine() + call writefile(['after'], 'Xsandboxstatusline_write') + return "status line" + endfunc + + func Check_statusline_in_sandbox(set_cmd0, set_cmd1) + new | only + call writefile(['before'], 'Xsandboxstatusline_write', 'D') + setlocal statusline= + exe 'sandbox' a:set_cmd0 'statusline=%!SandboxStatusLine()' + call assert_equal('', &l:statusline) + sandbox setlocal statusline=%!SandboxStatusLine() + call assert_fails('redrawstatus', 'E48:') + call assert_equal(['before'], readfile('Xsandboxstatusline_write')) + + setlocal statusline=%!SandboxStatusLine() | redrawstatus + call assert_equal('status line', Screenline(&lines - 1)) + call assert_equal(['after'], readfile('Xsandboxstatusline_write')) + + call writefile(['before'], 'Xsandboxstatusline_write') + setlocal statusline= + call assert_fails('redrawstatus', 'E48:') + call assert_equal(['before'], readfile('Xsandboxstatusline_write')) + + exe a:set_cmd1 'statusline=%!SandboxStatusLine()' | redrawstatus + call assert_equal('', &l:statusline) + call assert_equal('status line', Screenline(&lines - 1)) + call assert_equal(['after'], readfile('Xsandboxstatusline_write')) + bw! + endfunc + + call Check_statusline_in_sandbox('setglobal', 'setglobal') + call Check_statusline_in_sandbox('setglobal', 'set') + call Check_statusline_in_sandbox('set', 'setglobal') + call Check_statusline_in_sandbox('set', 'set') + + set statusline& + delfunc SandboxStatusLine + delfunc Check_statusline_in_sandbox +endfunc + " vim: shiftwidth=2 sts=2 expandtab