]> git.donarmstrong.com Git - lilypond.git/commitdiff
Introduce a maximum depth for markup evaluation
authorReinhold Kainhofer <reinhold@kainhofer.com>
Thu, 15 Sep 2011 13:36:48 +0000 (15:36 +0200)
committerReinhold Kainhofer <reinhold@kainhofer.com>
Mon, 19 Sep 2011 10:40:48 +0000 (12:40 +0200)
This will fix cases where a markup function calls itself
(or other functions) recursively with different arguments,
so the loop detection fails.

input/regression/markup-depth-non-terminating.ly [new file with mode: 0644]
lily/text-interface.cc
scm/lily.scm

diff --git a/input/regression/markup-depth-non-terminating.ly b/input/regression/markup-depth-non-terminating.ly
new file mode 100644 (file)
index 0000000..52e0f70
--- /dev/null
@@ -0,0 +1,15 @@
+\version "2.15.12"
+#(ly:set-option 'warning-as-error #f)
+
+\header {
+  texidoc = "Markups have a maximum depth to prevent non-termination."
+
+}
+
+% A simple markup function that calls itself and increases its argument, so
+% it will grow forever, unless we terminate it.
+#(define-markup-command (recursive-explosion layout props nr)
+  (number?)
+  (interpret-markup layout props (make-recursive-explosion-markup (+ nr 1))))
+
+\markup { Test: \recursive-explosion #1 }
index 5bd13641d737d3bb25dcd08cb6cc3d411a581b8b..232d9c3824a80bd36420c7c84dd9c07efd654ed8 100644 (file)
@@ -28,6 +28,7 @@
 #include "modified-font-metric.hh"
 #include "output-def.hh"
 #include "pango-font.hh"
+#include "program-option.hh"
 #include "international.hh"
 #include "warn.hh"
 
@@ -118,6 +119,19 @@ Text_interface::interpret_markup (SCM layout_smob, SCM props, SCM markup)
             }
         }
 
+      /* Check for non-terminating markups, e.g. recursive calls with
+       * changing arguments */
+      SCM opt_depth = ly_get_option (ly_symbol2scm ("max-markup-depth"));
+      size_t max_depth = robust_scm2int(opt_depth, 1024);
+      if (depth > max_depth)
+        {
+          string name = ly_symbol2string (scm_procedure_name (func));
+          // TODO: Also print the arguments of the markup!
+          non_fatal_error (_f("Markup depth exceeds maximal value of %d; "
+                              "Markup: %s", max_depth, name.c_str ()));
+          return Stencil().smobbed_copy ();
+        }
+
       encountered_markups.push_back (markup);
       SCM retval = scm_apply_2 (func, layout_smob, props, args);
       encountered_markups.pop_back ();
index ac735bc4893322d1318ba88fbeb403e3471fc029..f3ce9c33c0cb10215eafe252637df72ff719f566 100644 (file)
@@ -120,6 +120,9 @@ jobs.")
     (log-file #f
 "If string FOO is given as argument, redirect
 output to log file `FOO.log'.")
+    (max-markup-depth 1024
+"Maximum depth for the markup tree. If a markup has more levels, assume that
+it will not terminate at all and print out a warning, but continue processing.")
     (midi-extension ,(if (eq? PLATFORM 'windows)
                          "mid"
                          "midi")