From 174e560a23e40725cd0b50669a52d831342e5246 Mon Sep 17 00:00:00 2001 From: Peter Stephenson Date: Fri, 29 Sep 2017 16:46:01 +0100 Subject: 41787 (plus minor tweaks): use $FUNCSTACK for function nesting depth. Initialised from existing configuration value. --- ChangeLog | 7 +++++++ Doc/Zsh/params.yo | 10 ++++++++++ README | 26 +++++++++++++++++++++++++- Src/exec.c | 17 ++++++----------- Src/params.c | 14 ++++++++++++++ Test/C04funcdef.ztst | 8 ++++++++ configure.ac | 6 +++--- 7 files changed, 73 insertions(+), 15 deletions(-) diff --git a/ChangeLog b/ChangeLog index 2019a0fa7..f79a204ad 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2017-10-02 Peter Stephenson + + * 41787 (minor corrections): configure.ac, README, + Doc/Zsh/params.yo, Src/exec.c, Src/parms.c, + Test/C04funcdef.ztst: reduce default nested function depth to + 500 and expose as $FUNCNEST. + 2017-10-01 Peter Stephenson * 41797 (tweaked): Doc/Zsh/builtins.yo, Src/builtin.c, diff --git a/Doc/Zsh/params.yo b/Doc/Zsh/params.yo index 05ea45f98..5757111b2 100644 --- a/Doc/Zsh/params.yo +++ b/Doc/Zsh/params.yo @@ -731,6 +731,16 @@ This value is system dependent and is intended for debugging purposes. It is also useful with the tt(zsh/system) module which allows the number to be turned into a name or message. ) +vindex(FUNCNEST) +item(tt(FUNCNEST) )( +Integer. If greater than or equal to zero, the maximum nesting depth of +shell functions. When it is exceeded, an error is raised at the point +where a function is called. The default value is determined when +the shell is configured, but is typically 500. Increasing +the value increases the danger of a runaway function recursion +causing the shell to crash. Setting a negative value turns off +the check. +) vindex(GID) item(tt(GID) )( The real group ID of the shell process. If you have sufficient privileges, diff --git a/README b/README index 73733069d..6fad1d516 100644 --- a/README +++ b/README @@ -30,9 +30,33 @@ Zsh is a shell with lots of features. For a list of some of these, see the file FEATURES, and for the latest changes see NEWS. For more details, see the documentation. -Incompatibilities since 5.3.1 +Incompatibilities since 5.4.2 ----------------------------- +1) The default build-time maximum nested function depth has been +decreased from 1000 to 500 based on user experience. However, +it can now be changed at run time via the variable FUNCNEST. +If you previously configured the shell to set a different value, +or to remove the check, this is now reflected in the default +value of the variable. + +2) The syntax + +foo=([key]=value) + +can be used to set elements of arrays and associative arrays. In the +unlikely event that you need to set an array by matching files using a +pattern that starts with a character range followed by '=', you need to +quote the '=', e.g.: + +foo=([aeiou]\=vowel) + +This is only required for array values contained within parentheses; +command line expansion for normal arguments has not changed. + +Incompatibilities between 5.3.1 and 5.4.2 +----------------------------------------- + 1) The default behaviour of code like the following has changed: alias foo='noglob foo' diff --git a/Src/exec.c b/Src/exec.c index 780998b1a..dfb50c3b3 100644 --- a/Src/exec.c +++ b/Src/exec.c @@ -5508,9 +5508,7 @@ doshfunc(Shfunc shfunc, LinkList doshargs, int noreturnval) struct funcstack fstack; static int oflags; Emulation_options save_sticky = NULL; -#ifdef MAX_FUNCTION_DEPTH static int funcdepth; -#endif Heap funcheap; queue_signals(); /* Lots of memory and global state changes coming */ @@ -5640,13 +5638,12 @@ doshfunc(Shfunc shfunc, LinkList doshargs, int noreturnval) argzero = ztrdup(argzero); } } -#ifdef MAX_FUNCTION_DEPTH - if(++funcdepth > MAX_FUNCTION_DEPTH) - { - zerr("maximum nested function level reached"); - goto undoshfunc; - } -#endif + ++funcdepth; + if (zsh_funcnest >= 0 && funcdepth > zsh_funcnest) { + zerr("maximum nested function level reached; increase FUNCNEST?"); + lastval = 1; + goto undoshfunc; + } fstack.name = dupstring(name); /* * The caller is whatever is immediately before on the stack, @@ -5685,10 +5682,8 @@ doshfunc(Shfunc shfunc, LinkList doshargs, int noreturnval) runshfunc(prog, wrappers, fstack.name); doneshfunc: funcstack = fstack.prev; -#ifdef MAX_FUNCTION_DEPTH undoshfunc: --funcdepth; -#endif if (retflag) { retflag = 0; breaks = obreaks; diff --git a/Src/params.c b/Src/params.c index ddf3ce164..31ff0445b 100644 --- a/Src/params.c +++ b/Src/params.c @@ -101,6 +101,19 @@ zlong lastval, /* $? */ rprompt_indent, /* $ZLE_RPROMPT_INDENT */ ppid, /* $PPID */ zsh_subshell; /* $ZSH_SUBSHELL */ + +/* $FUNCNEST */ +/**/ +mod_export +zlong zsh_funcnest = +#ifdef MAX_FUNCTION_DEPTH + MAX_FUNCTION_DEPTH +#else + /* Disabled by default but can be enabled at run time */ + -1 +#endif + ; + /**/ zlong lineno, /* $LINENO */ zoptind, /* $OPTIND */ @@ -337,6 +350,7 @@ IPDEF5("COLUMNS", &zterm_columns, zlevar_gsu), IPDEF5("LINES", &zterm_lines, zlevar_gsu), IPDEF5U("ZLE_RPROMPT_INDENT", &rprompt_indent, rprompt_indent_gsu), IPDEF5("SHLVL", &shlvl, varinteger_gsu), +IPDEF5("FUNCNEST", &zsh_funcnest, varinteger_gsu), /* Don't import internal integer status variables. */ #define IPDEF6(A,B,F) {{NULL,A,PM_INTEGER|PM_SPECIAL|PM_DONTIMPORT},BR((void *)B),GSU(F),10,0,NULL,NULL,NULL,0} diff --git a/Test/C04funcdef.ztst b/Test/C04funcdef.ztst index 6a675e0b4..0c00a0477 100644 --- a/Test/C04funcdef.ztst +++ b/Test/C04funcdef.ztst @@ -515,6 +515,14 @@ 0:autoload with absolute path not cancelled by bare autoload >I have been loaded by explicit path. + ( + FUNCNEST=0 + fn() { true; } + fn + ) +1: +?fn:4: maximum nested function level reached; increase FUNCNEST? + %clean rm -f file.in file.out diff --git a/configure.ac b/configure.ac index ec0bdae6e..1a498f8b2 100644 --- a/configure.ac +++ b/configure.ac @@ -415,13 +415,13 @@ ifdef([max_function_depth],[undefine([max_function_depth])])dnl AH_TEMPLATE([MAX_FUNCTION_DEPTH], [Define for function depth limits]) AC_ARG_ENABLE(max-function-depth, -AC_HELP_STRING([--enable-max-function-depth=MAX], [limit function depth to MAX, default 1000]), +AC_HELP_STRING([--enable-max-function-depth=MAX], [limit function depth to MAX, default 500]), [if test x$enableval = xyes; then - AC_DEFINE(MAX_FUNCTION_DEPTH, 1000) + AC_DEFINE(MAX_FUNCTION_DEPTH, 500) elif test x$enableval != xno; then AC_DEFINE_UNQUOTED(MAX_FUNCTION_DEPTH, $enableval) fi], -[AC_DEFINE(MAX_FUNCTION_DEPTH, 1000)] +[AC_DEFINE(MAX_FUNCTION_DEPTH, 500)] ) ifdef([default_readnullcmd],[undefine([default_readnullcmd])])dnl -- cgit 1.4.1