# HG changeset patch # User John W. Eaton # Date 1272384424 14400 # Node ID cb08831272516afeec113d0a1eebbea8d411005e # Parent 87f879cf48fd9917247944e482f463e397019d81 limit on recursion via calls to source function diff -r 87f879cf48fd -r cb0883127251 src/ChangeLog --- a/src/ChangeLog Tue Apr 27 00:52:28 2010 -0400 +++ b/src/ChangeLog Tue Apr 27 12:07:04 2010 -0400 @@ -1,3 +1,15 @@ +2010-04-27 John W. Eaton + + * ov-usr-fcn.cc (octave_user_script::do_multi_index_op): + Correct spelling of max_recursion_depth in error message. + (octave_usr_fcn::do_multi_index_op): Ditto. + * pt-eval.h, pt-eval.cc (Vmax_recursion_depth): Move definition + here from ov-usr-fcn.cc. Now extern. + (Fmax_recursion_depth): Move definition here from ov-usr-fcn.cc. + * oct-parse.yy (source_file): Limit recursive calls on a + per-file basis. + Addresses bug #29491. + 2010-04-25 David Bateman * oct-parse.yy (octave_function * load_fcn_from_file diff -r 87f879cf48fd -r cb0883127251 src/oct-parse.yy --- a/src/oct-parse.yy Tue Apr 27 00:52:28 2010 -0400 +++ b/src/oct-parse.yy Tue Apr 27 12:07:04 2010 -0400 @@ -3877,8 +3877,45 @@ source_file (const std::string& file_name, const std::string& context, bool verbose, bool require_file, const std::string& warn_for) { + // Map from absolute name of script file to recursion level. We + // use a map instead of simply placing a limit on recursion in the + // source_file function so that two mutually recursive scripts + // written as + // + // foo1.m: + // ------ + // foo2 + // + // foo2.m: + // ------ + // foo1 + // + // and called with + // + // foo1 + // + // (for example) will behave the same if they are written as + // + // foo1.m: + // ------ + // source ("foo2.m") + // + // foo2.m: + // ------ + // source ("foo1.m") + // + // and called with + // + // source ("foo1.m") + // + // (for example). + + static std::map source_call_depth; + std::string file_full_name = file_ops::tilde_expand (file_name); + file_full_name = octave_env::make_absolute (file_full_name); + unwind_protect frame; frame.protect_var (curr_fcn_file_name); @@ -3887,6 +3924,19 @@ curr_fcn_file_name = file_name; curr_fcn_file_full_name = file_full_name; + if (source_call_depth.find (file_full_name) == source_call_depth.end ()) + source_call_depth[file_full_name] = -1; + + frame.protect_var (source_call_depth[file_full_name]); + + source_call_depth[file_full_name]++; + + if (source_call_depth[file_full_name] >= Vmax_recursion_depth) + { + error ("max_recursion_depth exceeded"); + return; + } + if (! context.empty ()) { if (context == "caller") diff -r 87f879cf48fd -r cb0883127251 src/ov-usr-fcn.cc --- a/src/ov-usr-fcn.cc Tue Apr 27 00:52:28 2010 -0400 +++ b/src/ov-usr-fcn.cc Tue Apr 27 12:07:04 2010 -0400 @@ -49,9 +49,6 @@ #include "parse.h" #include "variables.h" -// Maximum nesting level for functions called recursively. -static int Vmax_recursion_depth = 256; - // Whether to optimize subsasgn method calls. static bool Voptimize_subsasgn_calls = true; @@ -146,7 +143,7 @@ octave_call_stack::backtrace_error_message (); } else - ::error ("max_recursion_limit exceeded"); + ::error ("max_recursion_depth exceeded"); } } else @@ -339,7 +336,7 @@ if (call_depth >= Vmax_recursion_depth) { - ::error ("max_recursion_limit exceeded"); + ::error ("max_recursion_depth exceeded"); return retval; } @@ -668,18 +665,6 @@ return retval; } -DEFUN (max_recursion_depth, args, nargout, - "-*- texinfo -*-\n\ -@deftypefn {Built-in Function} {@var{val} =} max_recursion_depth ()\n\ -@deftypefnx {Built-in Function} {@var{old_val} =} max_recursion_depth (@var{new_val})\n\ -Query or set the internal limit on the number of times a function may\n\ -be called recursively. If the limit is exceeded, an error message is\n\ -printed and control returns to the top level.\n\ -@end deftypefn") -{ - return SET_INTERNAL_VARIABLE (max_recursion_depth); -} - DEFUN (optimize_subsasgn_calls, args, nargout, "-*- texinfo -*-\n\ @deftypefn {Built-in Function} {@var{val} =} optimize_subsasgn_calls ()\n\ diff -r 87f879cf48fd -r cb0883127251 src/pt-eval.cc --- a/src/pt-eval.cc Tue Apr 27 00:52:28 2010 -0400 +++ b/src/pt-eval.cc Tue Apr 27 12:07:04 2010 -0400 @@ -58,6 +58,10 @@ bool tree_evaluator::in_loop_command = false; +// Maximum nesting level for functions, scripts, or sourced files called +// recursively. +int Vmax_recursion_depth = 256; + // If TRUE, turn off printing of results in functions (as if a // semicolon has been appended to each statement). static bool Vsilent_functions = false; @@ -1168,6 +1172,18 @@ return ::do_keyboard (args); } +DEFUN (max_recursion_depth, args, nargout, + "-*- texinfo -*-\n\ +@deftypefn {Built-in Function} {@var{val} =} max_recursion_depth ()\n\ +@deftypefnx {Built-in Function} {@var{old_val} =} max_recursion_depth (@var{new_val})\n\ +Query or set the internal limit on the number of times a function may\n\ +be called recursively. If the limit is exceeded, an error message is\n\ +printed and control returns to the top level.\n\ +@end deftypefn") +{ + return SET_INTERNAL_VARIABLE (max_recursion_depth); +} + DEFUN (silent_functions, args, nargout, "-*- texinfo -*-\n\ @deftypefn {Built-in Function} {@var{val} =} silent_functions ()\n\ diff -r 87f879cf48fd -r cb0883127251 src/pt-eval.h --- a/src/pt-eval.h Tue Apr 27 00:52:28 2010 -0400 +++ b/src/pt-eval.h Tue Apr 27 12:07:04 2010 -0400 @@ -175,4 +175,8 @@ extern tree_evaluator *current_evaluator; +// Maximum nesting level for functions, scripts, or sourced files called +// recursively. +extern int Vmax_recursion_depth; + #endif