Problem: Option insecure flags not copied when splitting window.
Solution: Move window-local insecure flags to winopt_T and copy them
properly (zeertzjq).
closes: #18434
Signed-off-by: zeertzjq <zeertzjq@outlook.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
{
win_T *cw;
long winnr = 0;
- buf_T *save_curbuf;
int use_sandbox;
static char_u *result = NULL;
size_t len;
set_vim_var_string(VV_BEVAL_TEXT, text, -1);
vim_free(text);
- /*
- * Temporarily change the curbuf, so that we can determine whether
- * the buffer-local balloonexpr option was set insecurely.
- */
- save_curbuf = curbuf;
- curbuf = wp->w_buffer;
- use_sandbox = was_set_insecurely((char_u *)"balloonexpr",
- *curbuf->b_p_bexpr == NUL ? 0 : OPT_LOCAL);
- curbuf = save_curbuf;
+ use_sandbox = was_set_insecurely(wp, (char_u *)"balloonexpr",
+ *wp->w_buffer->b_p_bexpr == NUL ? 0 : OPT_LOCAL);
if (use_sandbox)
++sandbox;
++textlock;
#ifdef FEAT_EVAL
// if "fmt" was set insecurely it needs to be evaluated in the sandbox
- use_sandbox = was_set_insecurely(opt_name, opt_scope);
+ use_sandbox = was_set_insecurely(wp, opt_name, opt_scope);
// When the format starts with "%!" then evaluate it as an expression and
// use the result as the actual format string.
varnumber_T retval;
char_u *s;
sctx_T saved_sctx = current_sctx;
- int use_sandbox = was_set_insecurely((char_u *)"foldexpr",
+ int use_sandbox = was_set_insecurely(wp, (char_u *)"foldexpr",
OPT_LOCAL);
arg = skipwhite(wp->w_p_fde);
current_sctx = curbuf->b_p_script_ctx[BV_INEX];
res = eval_to_string_safe(curbuf->b_p_inex,
- was_set_insecurely((char_u *)"includeexpr", OPT_LOCAL),
+ was_set_insecurely(curwin, (char_u *)"includeexpr", OPT_LOCAL),
TRUE, TRUE);
set_vim_var_string(VV_FNAME, NULL, 0);
++emsg_off; // handle exceptions, but don't display errors
text = eval_to_string_safe(wp->w_p_fdt,
- was_set_insecurely((char_u *)"foldtext", OPT_LOCAL),
- TRUE, TRUE);
+ was_set_insecurely(wp, (char_u *)"foldtext", OPT_LOCAL),
+ TRUE, TRUE);
--emsg_off;
if (text == NULL || did_emsg)
colnr_T save_curswant;
int save_set_curswant;
int save_State;
- int use_sandbox = was_set_insecurely((char_u *)"indentexpr",
- OPT_LOCAL);
+ int use_sandbox = was_set_insecurely(curwin,
+ (char_u *)"indentexpr", OPT_LOCAL);
sctx_T save_sctx = current_sctx;
// Save and restore cursor position and curswant, in case it was changed
static void didset_options(void);
static void didset_options2(void);
#if defined(FEAT_EVAL) || defined(PROTO)
-static long_u *insecure_flag(int opt_idx, int opt_flags);
+static long_u *insecure_flag(win_T *wp, int opt_idx, int opt_flags);
#else
-# define insecure_flag(opt_idx, opt_flags) (&options[opt_idx].flags)
+# define insecure_flag(wp, opt_idx, opt_flags) (&options[opt_idx].flags)
#endif
static char *set_bool_option(int opt_idx, char_u *varp, int value, int opt_flags);
static char *set_num_option(int opt_idx, char_u *varp, long value, char *errbuf, size_t errbuflen, int opt_flags);
}
// The default value is not insecure.
- flagsp = insecure_flag(opt_idx, opt_flags);
+ flagsp = insecure_flag(curwin, opt_idx, opt_flags);
*flagsp = *flagsp & ~P_INSECURE;
if (both)
{
- flagsp = insecure_flag(opt_idx, OPT_LOCAL);
+ flagsp = insecure_flag(curwin, opt_idx, OPT_LOCAL);
*flagsp = *flagsp & ~P_INSECURE;
}
}
#endif
{
- long_u *p = insecure_flag(opt_idx, opt_flags);
+ long_u *p = insecure_flag(curwin, opt_idx, opt_flags);
int secure_saved = secure;
// When an option is set in the sandbox, from a modeline or in secure
// 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.
- flagsp = insecure_flag(opt_idx, opt_flags);
+ flagsp = insecure_flag(curwin, opt_idx, opt_flags);
if (both)
- flagsp_local = insecure_flag(opt_idx, OPT_LOCAL);
+ flagsp_local = insecure_flag(curwin, opt_idx, OPT_LOCAL);
if (!value_checked && (secure
#ifdef HAVE_SANDBOX
|| sandbox != 0
* Return -1 for an unknown option.
*/
int
-was_set_insecurely(char_u *opt, int opt_flags)
+was_set_insecurely(win_T *wp, char_u *opt, int opt_flags)
{
int idx = findoption(opt);
long_u *flagp;
if (idx >= 0)
{
- flagp = insecure_flag(idx, opt_flags);
+ flagp = insecure_flag(wp, idx, opt_flags);
return (*flagp & P_INSECURE) != 0;
}
internal_error("was_set_insecurely()");
* the option is used.
*/
static long_u *
-insecure_flag(int opt_idx, int opt_flags)
+insecure_flag(win_T *wp, int opt_idx, int opt_flags)
{
if (opt_flags & OPT_LOCAL)
switch ((int)options[opt_idx].indir)
{
- case PV_WRAP: return &curwin->w_p_wrap_flags;
+ case PV_WRAP: return &wp->w_p_wrap_flags;
#ifdef FEAT_STL_OPT
- case PV_STL: return &curwin->w_p_stl_flags;
+ case PV_STL: return &wp->w_p_stl_flags;
#endif
#ifdef FEAT_EVAL
# ifdef FEAT_FOLDING
- case PV_FDE: return &curwin->w_p_fde_flags;
- case PV_FDT: return &curwin->w_p_fdt_flags;
+ case PV_FDE: return &wp->w_p_fde_flags;
+ case PV_FDT: return &wp->w_p_fdt_flags;
# endif
# ifdef FEAT_BEVAL
- case PV_BEXPR: return &curbuf->b_p_bexpr_flags;
+ case PV_BEXPR: return &wp->w_buffer->b_p_bexpr_flags;
# endif
- case PV_INDE: return &curbuf->b_p_inde_flags;
- case PV_FEX: return &curbuf->b_p_fex_flags;
+ case PV_INDE: return &wp->w_buffer->b_p_inde_flags;
+ case PV_FEX: return &wp->w_buffer->b_p_fex_flags;
# ifdef FEAT_FIND_ID
- case PV_INEX: return &curbuf->b_p_inex_flags;
+ case PV_INEX: return &wp->w_buffer->b_p_inex_flags;
# endif
+#endif
+ }
+ else
+ // For global value of window-local options, use flags in w_allbuf_opt.
+ switch ((int)options[opt_idx].indir)
+ {
+ case PV_WRAP: return &wp->w_allbuf_opt.wo_wrap_flags;
+#if defined(FEAT_EVAL) && defined(FEAT_FOLDING)
+ case PV_FDE: return &wp->w_allbuf_opt.wo_fde_flags;
+ case PV_FDT: return &wp->w_allbuf_opt.wo_fdt_flags;
#endif
}
to->wo_lhi = from->wo_lhi;
#endif
+ to->wo_wrap_flags = from->wo_wrap_flags;
+#ifdef FEAT_STL_OPT
+ to->wo_stl_flags = from->wo_stl_flags;
+#endif
+#ifdef FEAT_EVAL
+ to->wo_fde_flags = from->wo_fde_flags;
+ to->wo_fdt_flags = from->wo_fdt_flags;
+#endif
+
#ifdef FEAT_EVAL
// Copy the script context so that we know where the value was last set.
mch_memmove(to->wo_script_ctx, from->wo_script_ctx,
void check_options(void);
int get_term_opt_idx(char_u **p);
int set_term_option_alloced(char_u **p);
-int was_set_insecurely(char_u *opt, int opt_flags);
+int was_set_insecurely(win_T *wp, char_u *opt, int opt_flags);
void redraw_titles(void);
int valid_name(char_u *val, char *allowed);
void set_option_sctx_idx(int opt_idx, int opt_flags, sctx_T script_ctx);
# define w_p_twk w_onebuf_opt.wo_twk // 'termwinkey'
char_u *wo_tws;
# define w_p_tws w_onebuf_opt.wo_tws // 'termwinsize'
+#endif
+
+ // A few options have local flags for P_INSECURE.
+ long_u wo_wrap_flags; // flags for 'wrap'
+#define w_p_wrap_flags w_onebuf_opt.wo_wrap_flags
+#ifdef FEAT_STL_OPT
+ long_u wo_stl_flags; // flags for 'statusline'
+# define w_p_stl_flags w_onebuf_opt.wo_stl_flags
+#endif
+#ifdef FEAT_EVAL
+ long_u wo_fde_flags; // flags for 'foldexpr'
+# define w_p_fde_flags w_onebuf_opt.wo_fde_flags
+ long_u wo_fdt_flags; // flags for 'foldtext'
+# define w_p_fdt_flags w_onebuf_opt.wo_fdt_flags
#endif
#ifdef FEAT_EVAL
// transform a pointer to a "onebuf" option into a "allbuf" option
#define GLOBAL_WO(p) ((char *)(p) + sizeof(winopt_T))
- // A few options have local flags for P_INSECURE.
- long_u w_p_wrap_flags; // flags for 'wrap'
-#ifdef FEAT_STL_OPT
- long_u w_p_stl_flags; // flags for 'statusline'
-#endif
-#ifdef FEAT_EVAL
- long_u w_p_fde_flags; // flags for 'foldexpr'
- long_u w_p_fdt_flags; // flags for 'foldtext'
-#endif
#if defined(FEAT_SIGNS) || defined(FEAT_FOLDING) || defined(FEAT_DIFF)
int *w_p_cc_cols; // array of columns to highlight or NULL
char_u w_p_culopt_flags; // flags for cursorline highlighting
#ifdef FEAT_EVAL
// if "fmt" was set insecurely it needs to be evaluated in the sandbox
- int use_sandbox = was_set_insecurely(opt_name, opt_scope);
+ int use_sandbox = was_set_insecurely(curwin, opt_name, opt_scope);
// When the format starts with "%!" then evaluate it as an expression and
// use the result as the actual format string.
call assert_equal('folded text', foldtextresult(1))
call assert_equal(['before'], readfile('Xmodelinefoldtext_write'))
+ split
+ call assert_equal('folded text', foldtextresult(1))
+ call assert_equal(['before'], readfile('Xmodelinefoldtext_write'))
+ close
+
setglobal foldtext=ModelineFoldText()
call assert_equal('folded text', foldtextresult(1))
call assert_equal(['before'], readfile('Xmodelinefoldtext_write'))
call Check_foldtext_in_modeline('setlocal')
call Check_foldtext_in_modeline('set')
+ new Xa
+ sandbox setglobal foldenable foldtext=ModelineFoldText()
+ setlocal bufhidden=wipe
+ call writefile(['before'], 'Xmodelinefoldtext_write', 'D')
+ edit! Xb
+ call setline(1, ['func T()', ' let i = 1', 'endfunc']) | %fold
+ 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'))
+ setlocal foldtext=ModelineFoldText()
+ call assert_equal('folded text', foldtextresult(1))
+ call assert_equal(['after'], readfile('Xmodelinefoldtext_write'))
+ setlocal bufhidden=wipe
+ call writefile(['before'], 'Xmodelinefoldtext_write', 'D')
+ edit! Xc
+ call setline(1, ['func T()', ' let i = 1', 'endfunc']) | %fold
+ call assert_equal('folded text', foldtextresult(1))
+ call assert_equal(['after'], readfile('Xmodelinefoldtext_write'))
+ bwipe!
+
set modeline& modelineexpr&
delfunc ModelineFoldText
delfunc Check_foldtext_in_modeline
call assert_equal(2, foldlevel(3))
call assert_equal(['before'], readfile('Xmodelinefoldexpr_write'))
+ split
+ call assert_equal(2, foldlevel(3))
+ call assert_equal(['before'], readfile('Xmodelinefoldexpr_write'))
+ close
+
setglobal foldexpr=ModelineFoldExpr()
call assert_equal(2, foldlevel(3))
call assert_equal(['before'], readfile('Xmodelinefoldexpr_write'))
call Check_foldexpr_in_modeline('setlocal')
call Check_foldexpr_in_modeline('set')
+ new Xa
+ sandbox setglobal foldenable foldmethod=expr foldexpr=ModelineFoldExpr()
+ setlocal bufhidden=wipe
+ call writefile(['before'], 'Xmodelinefoldexpr_write', 'D')
+ edit! Xb
+ call setline(1, lines[0:5])
+ 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'))
+ setlocal foldexpr=ModelineFoldExpr()
+ call assert_equal(2, foldlevel(3))
+ call assert_equal(['after'], readfile('Xmodelinefoldexpr_write'))
+ setlocal bufhidden=wipe
+ call writefile(['before'], 'Xmodelinefoldexpr_write', 'D')
+ edit! Xc
+ call setline(1, lines[0:5])
+ call assert_equal(2, foldlevel(3))
+ call assert_equal(['after'], readfile('Xmodelinefoldexpr_write'))
+ bwipe!
+
set modeline& modelineexpr&
delfunc ModelineFoldExpr
delfunc Check_foldexpr_in_modeline
\ 'ccc evil',
\ 'ddd vim: nowrap',
\ ], 'Xmodeline_nowrap', 'D')
- call NewWindow(10, 20)
+ set noequalalways
+ 11new | 20vsplit
func Check_modeline_nowrap(expect_insecure, expect_secure, set_cmd)
edit Xmodeline_nowrap
call assert_equal(a:expect_insecure, ScreenLines([1, 5], 20))
+
+ 5split
+ call assert_equal(a:expect_insecure, ScreenLines([1, 5], 20))
+ call assert_equal(a:expect_insecure, ScreenLines([7, 11], 20))
+
+ exe a:set_cmd 'nowrap'
+ call assert_equal(a:expect_secure, ScreenLines([1, 5], 20))
+ call assert_equal(a:expect_insecure, ScreenLines([7, 11], 20))
+
+ close
+ 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
call Check_modeline_nowrap(expect_insecure, expect_secure, 'setlocal')
call Check_modeline_nowrap(expect_insecure, expect_secure, 'set')
- call CloseWindow()
+ sandbox setglobal nowrap
+ setglobal list listchars=eol:$
+ setlocal bufhidden=wipe
+ enew!
+ call setline(1, ['aaa bbb'])
+ call assert_equal(['aaa >'], ScreenLines(1, 20))
+ setglobal nowrap
+ call assert_equal(['aaa >'], ScreenLines(1, 20))
+ setlocal nowrap
+ call assert_equal(['aaa '], ScreenLines(1, 20))
+ normal! 20zl
+ call assert_equal([' bbb$ '], ScreenLines(1, 20))
+ setlocal bufhidden=wipe
+ enew!
+ call setline(1, ['ccc ddd'])
+ call assert_equal(['ccc '], ScreenLines(1, 20))
+ normal! 20zl
+ call assert_equal([' ddd$ '], ScreenLines(1, 20))
+
+ bwipe!
delfunc Check_modeline_nowrap
+ set equalalways&
endfunc
" vim: shiftwidth=2 sts=2 expandtab
endfunc
func Check_statusline_in_sandbox(set_cmd0, set_cmd1)
- new | only
- call writefile(['before'], 'Xsandboxstatusline_write', 'D')
+ only
+ 11new | 20vsplit
+ call setline(1, 'foo')
+ windo setlocal statusline=SomethingElse
+ wincmd t
setlocal statusline=
+ call writefile(['before'], 'Xsandboxstatusline_write', 'D')
+
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'))
+ wincmd b
+ call assert_fails('redrawstatus!', 'E48:')
+ call assert_equal(['before'], readfile('Xsandboxstatusline_write'))
+ wincmd t
+
+ 5split
+ call assert_fails('redrawstatus!', 'E48:')
+ call assert_equal(['before'], readfile('Xsandboxstatusline_write'))
+ close
setlocal statusline=%!SandboxStatusLine() | redrawstatus
- call assert_equal('status line', Screenline(&lines - 1))
+ call assert_equal('status line', Screenline(12))
call assert_equal(['after'], readfile('Xsandboxstatusline_write'))
call writefile(['before'], 'Xsandboxstatusline_write')
call assert_fails('redrawstatus', 'E48:')
call assert_equal(['before'], readfile('Xsandboxstatusline_write'))
- exe a:set_cmd1 'statusline=%!SandboxStatusLine()' | redrawstatus
+ 5split
+ 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('status line', Screenline(6))
+ call assert_equal('status line', Screenline(12))
call assert_equal(['after'], readfile('Xsandboxstatusline_write'))
- bw!
+ bwipe!
endfunc
+ set noequalalways
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&
+ set equalalways& statusline&
delfunc SandboxStatusLine
delfunc Check_statusline_in_sandbox
endfunc
long count,
int c) // character to be inserted
{
- int use_sandbox = was_set_insecurely((char_u *)"formatexpr",
- OPT_LOCAL);
+ int use_sandbox = was_set_insecurely(curwin,
+ (char_u *)"formatexpr", OPT_LOCAL);
int r;
char_u *fex;
sctx_T save_sctx = current_sctx;
static int included_patches[] =
{ /* Add new patch number below this line */
+/**/
+ 1808,
/**/
1807,
/**/