Patch 8.2.2001
Problem:    Vim9: :def function does not apply 'maxfuncdepth'.
Solution:   Use 'maxfuncdepth'. (issue #7313)
Files:      src/vim9execute.c, src/userfunc.c, src/proto/userfunc.pro,
            src/testdir/test_vim9_func.vim


*** ../vim-8.2.2000/src/vim9execute.c   2020-11-12 12:08:47.982254065 +0100
--- src/vim9execute.c   2020-11-17 18:17:53.023959207 +0100
***************
*** 227,232 ****
--- 227,236 ----
                                                                       == FAIL)
        return FAIL;
  
+     // If depth of calling is getting too high, don't execute the function.
+     if (funcdepth_increment() == FAIL)
+       return FAIL;
+ 
      // Move the vararg-list to below the missing optional arguments.
      if (vararg_count > 0 && arg_to_add > 0)
        *STACK_TV_BOT(arg_to_add - 1) = *STACK_TV_BOT(-1);
***************
*** 503,508 ****
--- 507,513 ----
      ectx->ec_stack.ga_len = top + 1;
      *STACK_TV_BOT(-1) = *STACK_TV(idx);
  
+     funcdepth_decrement();
      return OK;
  }
  
***************
*** 835,840 ****
--- 840,846 ----
      cmdmod_T  save_cmdmod;
      int               restore_cmdmod = FALSE;
      int               trylevel_at_start = trylevel;
+     int               orig_funcdepth;
  
  // Get pointer to item in the stack.
  #define STACK_TV(idx) (((typval_T *)ectx.ec_stack.ga_data) + idx)
***************
*** 870,880 ****
--- 876,894 ----
        }
      }
  
+     // If depth of calling is getting too high, don't execute the function.
+     orig_funcdepth = funcdepth_get();
+     if (funcdepth_increment() == FAIL)
+       return FAIL;
+ 
      CLEAR_FIELD(ectx);
      ectx.ec_dfunc_idx = ufunc->uf_dfunc_idx;
      ga_init2(&ectx.ec_stack, sizeof(typval_T), 500);
      if (ga_grow(&ectx.ec_stack, 20) == FAIL)
+     {
+       funcdepth_decrement();
        return FAIL;
+     }
      ga_init2(&ectx.ec_trystack, sizeof(trycmd_T), 10);
      ga_init2(&ectx.ec_funcrefs, sizeof(partial_T *), 10);
  
***************
*** 2941,2946 ****
--- 2955,2961 ----
      if (ret != OK && did_emsg == did_emsg_before)
        semsg(_(e_unknown_error_while_executing_str),
                                                   printable_func_name(ufunc));
+     funcdepth_restore(orig_funcdepth);
      return ret;
  }
  
*** ../vim-8.2.2000/src/userfunc.c      2020-11-05 18:45:42.966909992 +0100
--- src/userfunc.c      2020-11-17 18:17:49.439966508 +0100
***************
*** 1373,1378 ****
--- 1373,1422 ----
      func_clear_free(fp, TRUE);
  }
  
+ static int    funcdepth = 0;
+ 
+ /*
+  * Increment the function call depth count.
+  * Return FAIL when going over 'maxfuncdepth'.
+  * Otherwise return OK, must call funcdepth_decrement() later!
+  */
+     int
+ funcdepth_increment(void)
+ {
+     if (funcdepth >= p_mfd)
+     {
+       emsg(_("E132: Function call depth is higher than 'maxfuncdepth'"));
+       return FAIL;
+     }
+     ++funcdepth;
+     return OK;
+ }
+ 
+     void
+ funcdepth_decrement(void)
+ {
+     --funcdepth;
+ }
+ 
+ /*
+  * Get the current function call depth.
+  */
+     int
+ funcdepth_get(void)
+ {
+     return funcdepth;
+ }
+ 
+ /*
+  * Restore the function call depth.  This is for cases where there is no
+  * garantee funcdepth_decrement() can be called exactly the same number of
+  * times as funcdepth_increment().
+  */
+     void
+ funcdepth_restore(int depth)
+ {
+     funcdepth = depth;
+ }
  
  /*
   * Call a user function.
***************
*** 1391,1397 ****
      funccall_T        *fc;
      int               save_did_emsg;
      int               default_arg_err = FALSE;
-     static int        depth = 0;
      dictitem_T        *v;
      int               fixvar_idx = 0; // index in fixvar[]
      int               i;
--- 1435,1440 ----
***************
*** 1406,1420 ****
  #endif
      ESTACK_CHECK_DECLARATION
  
!     // If depth of calling is getting too high, don't execute the function
!     if (depth >= p_mfd)
      {
-       emsg(_("E132: Function call depth is higher than 'maxfuncdepth'"));
        rettv->v_type = VAR_NUMBER;
        rettv->vval.v_number = -1;
        return;
      }
-     ++depth;
  
      line_breakcheck();                // check for CTRL-C hit
  
--- 1449,1461 ----
  #endif
      ESTACK_CHECK_DECLARATION
  
!     // If depth of calling is getting too high, don't execute the function.
!     if (funcdepth_increment() == FAIL)
      {
        rettv->v_type = VAR_NUMBER;
        rettv->vval.v_number = -1;
        return;
      }
  
      line_breakcheck();                // check for CTRL-C hit
  
***************
*** 1437,1443 ****
      {
        // Execute the function, possibly compiling it first.
        call_def_function(fp, argcount, argvars, funcexe->partial, rettv);
!       --depth;
        current_funccal = fc->caller;
        free_funccal(fc);
        return;
--- 1478,1484 ----
      {
        // Execute the function, possibly compiling it first.
        call_def_function(fp, argcount, argvars, funcexe->partial, rettv);
!       funcdepth_decrement();
        current_funccal = fc->caller;
        free_funccal(fc);
        return;
***************
*** 1783,1790 ****
      }
  
      did_emsg |= save_did_emsg;
!     --depth;
! 
      cleanup_function_call(fc);
  }
  
--- 1824,1830 ----
      }
  
      did_emsg |= save_did_emsg;
!     funcdepth_decrement();
      cleanup_function_call(fc);
  }
  
*** ../vim-8.2.2000/src/proto/userfunc.pro      2020-11-05 18:45:42.966909992 
+0100
--- src/proto/userfunc.pro      2020-11-17 18:17:45.811973886 +0100
***************
*** 14,19 ****
--- 14,23 ----
  int func_is_global(ufunc_T *ufunc);
  int func_name_refcount(char_u *name);
  void copy_func(char_u *lambda, char_u *global);
+ int funcdepth_increment(void);
+ void funcdepth_decrement(void);
+ int funcdepth_get(void);
+ void funcdepth_restore(int depth);
  int call_user_func_check(ufunc_T *fp, int argcount, typval_T *argvars, 
typval_T *rettv, funcexe_T *funcexe, dict_T *selfdict);
  void save_funccal(funccal_entry_T *entry);
  void restore_funccal(void);
*** ../vim-8.2.2000/src/testdir/test_vim9_func.vim      2020-11-05 
18:45:42.970909982 +0100
--- src/testdir/test_vim9_func.vim      2020-11-17 18:21:31.963501714 +0100
***************
*** 49,54 ****
--- 49,84 ----
    call delete('XTest_compile_error')
  enddef
  
+ def CallRecursive(n: number): number
+   return CallRecursive(n + 1)
+ enddef
+ 
+ def CallMapRecursive(l: list<number>): number
+   return map(l, {_, v -> CallMapRecursive([v])})[0]
+ enddef
+ 
+ def Test_funcdepth_error()
+   set maxfuncdepth=10
+ 
+   var caught = false
+   try
+     CallRecursive(1)
+   catch /E132:/
+     caught = true
+   endtry
+   assert_true(caught)
+ 
+   caught = false
+   try
+     CallMapRecursive([1])
+   catch /E132:/
+     caught = true
+   endtry
+   assert_true(caught)
+ 
+   set maxfuncdepth&
+ enddef
+ 
  def ReturnString(): string
    return 'string'
  enddef
*** ../vim-8.2.2000/src/version.c       2020-11-16 22:11:39.625599176 +0100
--- src/version.c       2020-11-17 18:22:21.927394611 +0100
***************
*** 752,753 ****
--- 752,755 ----
  {   /* Add new patch number below this line */
+ /**/
+     2001,
  /**/

-- 
hundred-and-one symptoms of being an internet addict:
264. You turn to the teletext page "surfing report" and are surprised that it
     is about sizes of waves and a weather forecast for seaside resorts.

 /// Bram Moolenaar -- [email protected] -- http://www.Moolenaar.net   \\\
///        sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\
\\\  an exciting new programming language -- http://www.Zimbu.org        ///
 \\\            help me help AIDS victims -- http://ICCF-Holland.org    ///

-- 
-- 
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 on the web visit 
https://groups.google.com/d/msgid/vim_dev/202011171723.0AHHNmW01496218%40masaka.moolenaar.net.

Raspunde prin e-mail lui