call v9.CheckLegacyAndVim9Success(lines)
endfunc
+" Note: legacy func, not vim9 def, to avoid the test file being vim9script
+func Test_vim9_def_fc_sandbox()
+ sandbox def! g:Bad()
+ system('echo unsafe')
+ enddef
+
+ call assert_fails('call g:Bad()', 'E48:')
+ delfunction g:Bad
+endfunc
+
+func Test_vim9_def_call_dfunc_fc_sandbox()
+ " Inner has FC_SANDBOX, outer does not.
+ " Calling outer goes through call_dfunc into inner, exercising
+ " the sandbox handling in call_dfunc and func_return.
+ sandbox def! g:Inner()
+ system('echo unsafe')
+ enddef
+
+ def! g:Outer()
+ g:Inner()
+ enddef
+
+ call assert_fails('call g:Outer()', 'E48:')
+ delfunction g:Inner
+ delfunction g:Outer
+endfunc
+
+" Deferred body inside a sandboxed def function must still run sandboxed.
+func Test_vim9_def_defer_fc_sandbox()
+ sandbox def! g:BadDefer()
+ defer system('echo unsafe')
+ enddef
+
+ call assert_fails('call g:BadDefer()', 'E48:')
+ delfunction g:BadDefer
+endfunc
+
" vim: shiftwidth=2 sts=2 expandtab
if (fp->uf_def_status != UF_NOT_COMPILED)
{
+ if (fp->uf_flags & FC_SANDBOX)
+ {
+ using_sandbox = TRUE;
+ ++sandbox;
+ }
#ifdef FEAT_PROFILE
ufunc_T *caller = fc->fc_caller == NULL ? NULL : fc->fc_caller->fc_func;
#endif
if (call_def_function(fp, argcount, argvars, 0,
funcexe->fe_partial, funcexe->fe_object, fc, rettv) == FAIL)
retval = FCERR_FAILED;
+ if (using_sandbox)
+ --sandbox;
funcdepth_decrement();
#ifdef FEAT_PROFILE
if (do_profiling == PROF_YES && (fp->uf_profiling
static int included_patches[] =
{ /* Add new patch number below this line */
+/**/
+ 403,
/**/
402,
/**/
else
ectx->ec_outer_ref = NULL;
+ if (ufunc->uf_flags & FC_SANDBOX)
+ ++sandbox;
+
++ufunc->uf_calls;
// Set execution state to the start of the called function.
if (dfunc->df_defer_var_idx > 0)
invoke_defer_funcs(ectx);
+ if (dfunc->df_ufunc->uf_flags & FC_SANDBOX)
+ --sandbox;
+
// No check for uf_refcount being zero, cannot think of a way that would
// happen.
--dfunc->df_ufunc->uf_calls;