diff src/oct-parse.yy @ 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 a61d7248627c
children 8baff2aceabc
line wrap: on
line diff
--- 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")