From 52ccb98354af7f1bd10b171c920d203878b355fd Mon Sep 17 00:00:00 2001 From: Bernhard Roider Date: Sat, 23 Feb 2008 20:38:57 +0000 Subject: [PATCH] Fix crash due to recursive function call when a counter references itself. e.g.: Counter Name Version LabelString "\theVersion.0" End git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@23166 a592a061-630c-0410-9148-cb99ea01b6c8 --- src/Counters.cpp | 46 ++++++++++++++++++++++++++++++++++++---------- src/Counters.h | 8 +++++++- 2 files changed, 43 insertions(+), 11 deletions(-) diff --git a/src/Counters.cpp b/src/Counters.cpp index cec6672974..39e177b1f6 100644 --- a/src/Counters.cpp +++ b/src/Counters.cpp @@ -339,23 +339,48 @@ docstring Counters::labelItem(docstring const & ctr, docstring Counters::theCounter(docstring const & counter) +{ + std::set callers; + return theCounter(counter, callers); +} + +docstring Counters::theCounter(docstring const & counter, + std::set & callers) { if (!hasCounter(counter)) return from_ascii("??"); - Counter const & c = counterList[counter]; - docstring ls = appendix() ? c.labelStringAppendix() : c.labelString(); + docstring label; - if (ls.empty()) { - if (!c.master().empty()) - ls = from_ascii("\\the") + c.master() + from_ascii("."); - ls += from_ascii("\\arabic{") + counter + "}"; + if (callers.find(counter) == callers.end()) { + + pair::iterator, bool> result = callers.insert(counter); + + Counter const & c = counterList[counter]; + docstring ls = appendix() ? c.labelStringAppendix() : c.labelString(); + + if (ls.empty()) { + if (!c.master().empty()) + ls = from_ascii("\\the") + c.master() + from_ascii("."); + ls += from_ascii("\\arabic{") + counter + "}"; + } + + label = counterLabel(ls, &callers); + + callers.erase(result.first); + } else { + // recursion detected + lyxerr << "Warning: Recursion in label for counter `" + << counter << "' detected" + << endl; } - return counterLabel(ls); + + return label; } -docstring Counters::counterLabel(docstring const & format) +docstring Counters::counterLabel(docstring const & format, + std::set * callers) { docstring label = format; @@ -373,10 +398,11 @@ docstring Counters::counterLabel(docstring const & format) && lowercase(label[k]) <= 'z') ++k; docstring counter = label.substr(j, k - j); - docstring repl = theCounter(counter); + docstring repl = callers? theCounter(counter, *callers): + theCounter(counter); label.replace(i, k - j + 4, repl); } - + while (true) { //lyxerr << "label=" << to_utf8(label) << endl; diff --git a/src/Counters.h b/src/Counters.h index f2d4df7157..f7d2cea134 100644 --- a/src/Counters.h +++ b/src/Counters.h @@ -18,6 +18,7 @@ #include "support/docstring.h" #include +#include namespace lyx { @@ -105,7 +106,8 @@ public: docstring theCounter(docstring const & c); /// Replace om format all the LaTeX-like macros that depend on /// counters. - docstring counterLabel(docstring const & format); + docstring counterLabel(docstring const & format, + std::set * callers = 0); /// Are we in apendix? bool appendix() const { return appendix_; }; /// Set the state variable indicating whether we are in appendix. @@ -115,6 +117,10 @@ public: /// Sets the current enclosing float. void current_float(std::string const & f) { current_float_ = f; } private: + /// returns the expanded string representation of the counter + /// with recursion protection through callers. + docstring theCounter(docstring const & c, + std::set & callers); /// Returns the value of the counter according to the /// numbering scheme numbertype. /* Available numbering schemes are arabic (1, 2,...), roman