From: Vladimír Vondruš Date: Tue, 15 May 2018 15:25:25 +0000 (+0200) Subject: doxygen: don't crash during search building on too long function arguments. X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~cjwatson/git?a=commitdiff_plain;h=4df10c4afc3baedc711e75e8f902bbfe502b4abc;p=blog.git doxygen: don't crash during search building on too long function arguments. In some very pathological cases the function parameter list might exceed 256 characters, which won't fit in the serialized data. But that also won't fit in the search result list so there's no point in storing so much. Truncating to 65 characters and adding an ellipsis after. --- diff --git a/doxygen/dox2html5.py b/doxygen/dox2html5.py index c70df8c7..5c3b78a9 100755 --- a/doxygen/dox2html5.py +++ b/doxygen/dox2html5.py @@ -1870,9 +1870,21 @@ def build_search_data(state: State, merge_subtrees=True, add_lookahead_barriers= name = result.name suffix_length = 0 if hasattr(result, 'params') and result.params is not None: - params = strip_tags(', '.join(result.params)) - name_with_args += '(' + params + ')' - suffix_length += len(html.unescape(params)) + 2 + # Some very heavily templated function parameters might cause + # the suffix_length to exceed 256, which won't fit into the + # serialized search data. However that *also* won't fit in the + # search result list so there's no point in storing so much. + # Truncate it to 65 chars which could fit at least a part of + # the function name in the list in most cases, yet be still + # long enough to be able to distinguish particular overloads. + # TODO: the suffix_length has to be calculated on UTF-8 and I + # am (un)escaping a lot back and forth here -- needs to be + # cleaned up + params = html.unescape(strip_tags(', '.join(result.params))) + if len(params) > 65: + params = params[:64] + '…' + name_with_args += '(' + html.escape(params) + ')' + suffix_length += len(params.encode('utf-8')) + 2 if hasattr(result, 'suffix') and result.suffix: name_with_args += result.suffix # TODO: escape elsewhere so i don't have to unescape here diff --git a/doxygen/test/search_long_suffix_length/Doxyfile b/doxygen/test/search_long_suffix_length/Doxyfile new file mode 100644 index 00000000..44b01a48 --- /dev/null +++ b/doxygen/test/search_long_suffix_length/Doxyfile @@ -0,0 +1,13 @@ +INPUT = File.h +QUIET = YES +GENERATE_HTML = NO +GENERATE_LATEX = NO +GENERATE_XML = YES +XML_PROGRAMLISTING = NO + +M_PAGE_FINE_PRINT = +M_THEME_COLOR = +M_FAVICON = +M_LINKS_NAVBAR1 = +M_LINKS_NAVBAR2 = +M_SEARCH_DOWNLOAD_BINARY = YES diff --git a/doxygen/test/search_long_suffix_length/File.h b/doxygen/test/search_long_suffix_length/File.h new file mode 100644 index 00000000..8326f7cb --- /dev/null +++ b/doxygen/test/search_long_suffix_length/File.h @@ -0,0 +1,10 @@ +#include +#include +#include + +/** @file + * @brief A file + */ + +/** @brief One fun function */ +bool aVeryLongFunctionName(const std::reference_wrapper>& a, const std::reference_wrapper>& b, const std::reference_wrapper>& c, const std::reference_wrapper>& d, const std::reference_wrapper>& e, const std::reference_wrapper>& f, const std::reference_wrapper>& g); diff --git a/doxygen/test/test_search.py b/doxygen/test/test_search.py index a8c5da75..05dfb2df 100755 --- a/doxygen/test/test_search.py +++ b/doxygen/test/test_search.py @@ -536,6 +536,34 @@ union [58] 59: glUnion() [alias=58] -> """.strip()) +class SearchLongSuffixLength(IntegrationTestCase): + def __init__(self, *args, **kwargs): + super().__init__(__file__, 'long_suffix_length', *args, **kwargs) + + def test(self): + self.run_dox2html5(index_pages=[], wildcard='*.xml') + + with open(os.path.join(self.path, 'html', 'searchdata.bin'), 'rb') as f: + serialized = f.read() + search_data_pretty = pretty_print(serialized)[0] + #print(search_data_pretty) + self.assertEqual(len(serialized), 382) + # The parameters get cut off with an ellipsis + self.assertEqual(search_data_pretty, """ +2 symbols +file.h [2] +| :$ +| :averylongfunctionname [0] +| ($ +| ) [1] +averylongfunctionname [0] +| ($ +| ) [1] +0: ::aVeryLongFunctionName(const std::reference_wrapper>&, c…) [prefix=2[:12], suffix_length=69, type=FUNC] -> #a1e9a11887275938ef5541070955c9d9c +1: [prefix=0[:46], suffix_length=67, type=FUNC] -> +2: File.h [type=FILE] -> File_8h.html +""".strip()) + if __name__ == '__main__': # pragma: no cover parser = argparse.ArgumentParser() parser.add_argument('file', help="file to pretty-print")