commit b7a1eb68e1456fb04a95207624717da0a724b3be
Author: Richard Heck <[email protected]>
Date:   Mon Feb 10 23:11:35 2014 -0500

    Fix bug #8944 by introducing a maximum size for keys we process.
    The problem is caused by the fact that Encodings::fromLaTeXCommand
    is very slow. It's not clear to me if that can be fixed, or if that
    is just how things are. Georg suggested another time that we might
    use tex2lyx in or instead of convertLatexCommands() in BiblioInfo.cpp,
    but I don't know if that would much faster. The author string in the
    example file is 32K characters long. As long as some files tex2lyx
    would convert.

diff --git a/src/BiblioInfo.cpp b/src/BiblioInfo.cpp
index 49e6677..2460c48 100644
--- a/src/BiblioInfo.cpp
+++ b/src/BiblioInfo.cpp
@@ -271,9 +271,9 @@ docstring const BibTeXInfo::getAbbreviatedAuthor(bool 
jurabib_style) const
                return authors;
        }
 
-       docstring author = convertLaTeXCommands(operator[]("author"));
+       docstring author = operator[]("author");
        if (author.empty()) {
-               author = convertLaTeXCommands(operator[]("editor"));
+               author = operator[]("editor");
                if (author.empty())
                        return author;
        }
@@ -291,18 +291,20 @@ docstring const BibTeXInfo::getAbbreviatedAuthor(bool 
jurabib_style) const
                        + "/" + familyName(authors[1]);
                if (authors.size() == 3)
                        shortauthor += "/" + familyName(authors[2]);
-               return shortauthor;
+               return convertLaTeXCommands(shortauthor);
        }
 
+       docstring retval = familyName(authors[0]);
+
        if (authors.size() == 2 && authors[1] != "others")
-               return bformat(from_ascii("%1$s and %2$s"),
+               retval = bformat(from_ascii("%1$s and %2$s"),
                        familyName(authors[0]), familyName(authors[1]));
 
        if (authors.size() >= 2)
-               return bformat(from_ascii("%1$s et al."),
+               retval = bformat(from_ascii("%1$s et al."),
                        familyName(authors[0]));
 
-       return familyName(authors[0]);
+       return convertLaTeXCommands(retval);
 }
 
 
@@ -471,6 +473,11 @@ docstring BibTeXInfo::expandFormat(docstring const & 
format,
 {
        // incorrect use of macros could put us in an infinite loop
        static int max_passes = 5000;
+       // the use of overly large keys can lead to performance problems, due
+       // to eventual attempts to convert LaTeX macros to unicode. See bug
+       // #8944. This is perhaps not the best solution, but it will have to
+       // do for now.
+       static size_t max_keysize = 128;
        odocstringstream ret; // return value
        string key;
        bool scanning_key = false;
@@ -509,7 +516,7 @@ docstring BibTeXInfo::expandFormat(docstring const & format,
                                        ret << trans;
                                } else {
                                        docstring const val =
-                                               getValueForKey(key, buf, 
before, after, dialog, xref);
+                                               getValueForKey(key, buf, 
before, after, dialog, xref, max_keysize);
                                        if (!scanning_rich)
                                                ret << from_ascii("{!<span 
class=\"bib-" + key + "\">!}");
                                        ret << val;
@@ -664,8 +671,10 @@ docstring const & BibTeXInfo::operator[](string const & 
field) const
 
 docstring BibTeXInfo::getValueForKey(string const & oldkey, Buffer const & buf,
        docstring const & before, docstring const & after, docstring const & 
dialog,
-       BibTeXInfo const * const xref) const
+       BibTeXInfo const * const xref, size_t maxsize) const
 {
+       // anything less is pointless
+       LASSERT(maxsize >= 16, maxsize = 16);
        string key = oldkey;
        bool cleanit = false;
        if (prefixIs(oldkey, "clean:")) {
@@ -724,9 +733,13 @@ docstring BibTeXInfo::getValueForKey(string const & 
oldkey, Buffer const & buf,
                else if (key == "year")
                        ret = getYear();
        }
+
        if (cleanit)
-               return html::cleanAttr(ret);
+               ret = html::cleanAttr(ret);
 
+       // make sure it is not too big
+       if (ret.size() > maxsize)
+               ret = ret.substr(0, maxsize - 3) + from_ascii("...");
        return ret;
 }
 
diff --git a/src/BiblioInfo.h b/src/BiblioInfo.h
index 095221d..36750d8 100644
--- a/src/BiblioInfo.h
+++ b/src/BiblioInfo.h
@@ -114,7 +114,7 @@ private:
        /// be the one referenced in the crossref field.
        docstring getValueForKey(std::string const & key, Buffer const & buf,
                docstring const & before, docstring const & after, docstring 
const & dialog,
-               BibTeXInfo const * const xref = 0) const;
+               BibTeXInfo const * const xref, size_t maxsize = 1024) const;
        /// replace %keys% in a format string with their values
        /// called from getInfo()
        /// format strings may contain:

Reply via email to