From e66073bc94cad6c13c2f6c35d5e3d794f6a00a2c Mon Sep 17 00:00:00 2001 From: Maxime Coste Date: Sun, 11 Mar 2018 11:40:26 +1100 Subject: [PATCH] Detect infinit recursion in reference highlighting Reference highlighters allow for potential mutual recursion between highlighters. This is usually fine, but if the recursion happens on the same buffer range, it means we will recurse infinitely. Fixes #1920 --- src/highlighters.cc | 8 ++++++++ test/regression/1920-crash-on-python-in-docstring/cmd | 1 + test/regression/1920-crash-on-python-in-docstring/display | 6 ++++++ test/regression/1920-crash-on-python-in-docstring/in | 1 + test/regression/1920-crash-on-python-in-docstring/rc | 3 +++ 5 files changed, 19 insertions(+) create mode 100644 test/regression/1920-crash-on-python-in-docstring/cmd create mode 100644 test/regression/1920-crash-on-python-in-docstring/display create mode 100644 test/regression/1920-crash-on-python-in-docstring/in create mode 100644 test/regression/1920-crash-on-python-in-docstring/rc diff --git a/src/highlighters.cc b/src/highlighters.cc index 41953aa4..864c7449 100644 --- a/src/highlighters.cc +++ b/src/highlighters.cc @@ -1581,6 +1581,14 @@ struct ReferenceHighlighter : Highlighter private: void do_highlight(HighlightContext context, DisplayBuffer& display_buffer, BufferRange range) override { + static Vector> running_refs; + const std::pair desc{m_name, range}; + if (contains(running_refs, desc)) + return write_to_debug_buffer(format("highlighting recursion detected with ref to {}", m_name)); + + running_refs.push_back(desc); + auto pop_desc = on_scope_end([] { running_refs.pop_back(); }); + try { DefinedHighlighters::instance().get_child(m_name).highlight(context, display_buffer, range); diff --git a/test/regression/1920-crash-on-python-in-docstring/cmd b/test/regression/1920-crash-on-python-in-docstring/cmd new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/test/regression/1920-crash-on-python-in-docstring/cmd @@ -0,0 +1 @@ + diff --git a/test/regression/1920-crash-on-python-in-docstring/display b/test/regression/1920-crash-on-python-in-docstring/display new file mode 100644 index 00000000..c74fa31e --- /dev/null +++ b/test/regression/1920-crash-on-python-in-docstring/display @@ -0,0 +1,6 @@ +{ "jsonrpc": "2.0", "method": "draw", "params": [[[{ "face": { "fg": "black", "bg": "white", "attributes": [] }, "contents": "\"" }, { "face": { "fg": "magenta", "bg": "default", "attributes": [] }, "contents": "\"\">>> " }, { "face": { "fg": "default", "bg": "default", "attributes": [] }, "contents": "\"\"\"\u000a" }]], { "fg": "default", "bg": "default", "attributes": [] }, { "fg": "blue", "bg": "default", "attributes": [] }] } +{ "jsonrpc": "2.0", "method": "menu_hide", "params": [] } +{ "jsonrpc": "2.0", "method": "info_hide", "params": [] } +{ "jsonrpc": "2.0", "method": "draw_status", "params": [[], [{ "face": { "fg": "default", "bg": "default", "attributes": [] }, "contents": "out 1:1 " }, { "face": { "fg": "black", "bg": "yellow", "attributes": [] }, "contents": "" }, { "face": { "fg": "default", "bg": "default", "attributes": [] }, "contents": " " }, { "face": { "fg": "blue", "bg": "default", "attributes": [] }, "contents": "1 sel" }, { "face": { "fg": "default", "bg": "default", "attributes": [] }, "contents": " - unnamed0@[kak-tests]" }], { "fg": "cyan", "bg": "default", "attributes": [] }] } +{ "jsonrpc": "2.0", "method": "set_cursor", "params": ["buffer", { "line": 0, "column": 0 }] } +{ "jsonrpc": "2.0", "method": "refresh", "params": [true] } diff --git a/test/regression/1920-crash-on-python-in-docstring/in b/test/regression/1920-crash-on-python-in-docstring/in new file mode 100644 index 00000000..2a40350c --- /dev/null +++ b/test/regression/1920-crash-on-python-in-docstring/in @@ -0,0 +1 @@ +""">>> """ diff --git a/test/regression/1920-crash-on-python-in-docstring/rc b/test/regression/1920-crash-on-python-in-docstring/rc new file mode 100644 index 00000000..909f53ff --- /dev/null +++ b/test/regression/1920-crash-on-python-in-docstring/rc @@ -0,0 +1,3 @@ +source "%val{runtime}/colors/default.kak" +source "%val{runtime}/rc/core/python.kak" +set buffer filetype python