Mercurial > hg > octave-avbm
changeset 10578:cb0883127251
limit on recursion via calls to source function
author | John W. Eaton <jwe@octave.org> |
---|---|
date | Tue, 27 Apr 2010 12:07:04 -0400 |
parents | 87f879cf48fd |
children | fd6899b1b00e |
files | src/ChangeLog src/oct-parse.yy src/ov-usr-fcn.cc src/pt-eval.cc src/pt-eval.h |
diffstat | 5 files changed, 84 insertions(+), 17 deletions(-) [+] |
line wrap: on
line diff
--- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,15 @@ +2010-04-27 John W. Eaton <jwe@octave.org> + + * 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 <dbateman@free.fr> * oct-parse.yy (octave_function * load_fcn_from_file
--- a/src/oct-parse.yy +++ b/src/oct-parse.yy @@ -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<std::string, int> 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")
--- a/src/ov-usr-fcn.cc +++ b/src/ov-usr-fcn.cc @@ -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\
--- a/src/pt-eval.cc +++ b/src/pt-eval.cc @@ -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\