diff --git a/src/option.c b/src/option.c index 4a4d21b881..8a495e087a 100644 --- a/src/option.c +++ b/src/option.c @@ -831,6 +831,11 @@ set_option_default( // The default value is not insecure. flagsp = insecure_flag(opt_idx, opt_flags); *flagsp = *flagsp & ~P_INSECURE; + if (both) + { + flagsp = insecure_flag(opt_idx, OPT_LOCAL); + *flagsp = *flagsp & ~P_INSECURE; + } } #ifdef FEAT_EVAL @@ -2781,22 +2786,34 @@ did_set_option( int value_checked) // value was checked to be safe, no need to set the // P_INSECURE flag. { - long_u *p; + long_u *flagsp; + long_u *flagsp_local = NULL; + int both = (opt_flags & (OPT_LOCAL | OPT_GLOBAL)) == 0; options[opt_idx].flags |= P_WAS_SET; // When an option is set in the sandbox, from a modeline or in secure mode // set the P_INSECURE flag. Otherwise, if a new value is stored reset the // flag. - p = insecure_flag(opt_idx, opt_flags); + flagsp = insecure_flag(opt_idx, opt_flags); + if (both) + flagsp_local = insecure_flag(opt_idx, OPT_LOCAL); if (!value_checked && (secure #ifdef HAVE_SANDBOX || sandbox != 0 #endif || (opt_flags & OPT_MODELINE))) - *p = *p | P_INSECURE; + { + *flagsp = *flagsp | P_INSECURE; + if (flagsp_local != NULL) + *flagsp_local = *flagsp_local | P_INSECURE; + } else if (new_value) - *p = *p & ~P_INSECURE; + { + *flagsp = *flagsp & ~P_INSECURE; + if (flagsp_local != NULL) + *flagsp_local = *flagsp_local & ~P_INSECURE; + } } /* diff --git a/src/testdir/test_fold.vim b/src/testdir/test_fold.vim index fc63b1572b..3a00d9c2cd 100644 --- a/src/testdir/test_fold.vim +++ b/src/testdir/test_fold.vim @@ -1669,7 +1669,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 @@ -1680,24 +1680,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 @@ -1711,15 +1738,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/src/testdir/test_modeline.vim b/src/testdir/test_modeline.vim index a5762f7f6b..cb144c580a 100644 --- a/src/testdir/test_modeline.vim +++ b/src/testdir/test_modeline.vim @@ -371,8 +371,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 ', @@ -380,9 +394,6 @@ func Test_modeline_nowrap_lcs_extends() \ 'ddd >', \ '~ ', \ ] - call assert_equal(expect_insecure, ScreenLines([1, 5], 20)) - - setlocal nowrap let expect_secure = [ \ 'aaa ', \ 'bbb ', @@ -390,7 +401,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 = [ @@ -401,13 +413,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/src/testdir/test_statusline.vim b/src/testdir/test_statusline.vim index 401eb2a046..e1f6359401 100644 --- a/src/testdir/test_statusline.vim +++ b/src/testdir/test_statusline.vim @@ -637,4 +637,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 diff --git a/src/version.c b/src/version.c index 900a682f88..ba653958a5 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 */ +/**/ + 1807, /**/ 1806, /**/