diff options
author | Daniel Levin <dendy.ua@gmail.com> | 2018-10-31 03:45:42 -0700 |
---|---|---|
committer | Daniel Levin <dendy.ua@gmail.com> | 2018-11-08 08:29:50 +0000 |
commit | 68e780f99ddb26cd35c5d3cbcf79d59fae663c24 (patch) | |
tree | 984d19a0e903b66f079c09d9a78e591ae2515781 /src/plugins/texteditor/generichighlighter | |
parent | d84672226447259166fb2f897ca1915b8b234ba5 (diff) |
Fix infinite recursion in highlight processor
Highlight definitions might have a case with recursive context call.
Trivial example:
<context name="foo" fallthroughContext="bar">
<context name="bar" fallthroughContext="#pop">
This leads to infinite recursion call or infinite while loop in
Highlighter::highlightBlock. Some safety measures should
be implemented, like Kate does.
Implementation should detect recursion call and stop processing current
line. I.e. when iterateThroughRules() was already called with exactly
the same current context and progress->offset().
This patch implements recursion detection in ProgressData instance.
Task-number: QTCREATORBUG-21411
Change-Id: I4e1ba13ce40b7ba0f64ec655f8ce4b6e406ccf97
Reviewed-by: Orgad Shaneh <orgads@gmail.com>
Reviewed-by: David Schulz <david.schulz@qt.io>
Diffstat (limited to 'src/plugins/texteditor/generichighlighter')
3 files changed, 26 insertions, 0 deletions
diff --git a/src/plugins/texteditor/generichighlighter/highlighter.cpp b/src/plugins/texteditor/generichighlighter/highlighter.cpp index f7004e878c..e4d07adef9 100644 --- a/src/plugins/texteditor/generichighlighter/highlighter.cpp +++ b/src/plugins/texteditor/generichighlighter/highlighter.cpp @@ -337,6 +337,13 @@ void Highlighter::iterateThroughRules(const QString &text, const bool childRule, const QList<QSharedPointer<Rule> > &rules) { + if (!childRule) { + if (progress->detectRecursion(m_currentContext->id())) { + progress->setOffset(length); + return; + } + } + typedef QList<QSharedPointer<Rule> >::const_iterator RuleIterator; bool contextChanged = false; diff --git a/src/plugins/texteditor/generichighlighter/progressdata.cpp b/src/plugins/texteditor/generichighlighter/progressdata.cpp index d79d5b0152..a6453c8399 100644 --- a/src/plugins/texteditor/generichighlighter/progressdata.cpp +++ b/src/plugins/texteditor/generichighlighter/progressdata.cpp @@ -113,3 +113,18 @@ void ProgressData::unTrackRule(Rule *rule) { m_trackedRules.removeAll(rule); } + +bool ProgressData::detectRecursion(const QString &contextId) +{ + if (m_offset != m_iterationOffset) { + m_iterationOffset = m_offset; + m_iterationContextIds.clear(); + } + + if (m_iterationContextIds.contains(contextId)) + return true; + + m_iterationContextIds.append(contextId); + + return false; +} diff --git a/src/plugins/texteditor/generichighlighter/progressdata.h b/src/plugins/texteditor/generichighlighter/progressdata.h index d2b158146d..7350eb0d04 100644 --- a/src/plugins/texteditor/generichighlighter/progressdata.h +++ b/src/plugins/texteditor/generichighlighter/progressdata.h @@ -67,6 +67,8 @@ public: void trackRule(Rule *rule); void unTrackRule(Rule *rule); + bool detectRecursion(const QString &contextId); + private: int m_offset; int m_savedOffset; @@ -76,6 +78,8 @@ private: bool m_willContinueLine; QStringList m_captures; QList<Rule *> m_trackedRules; + int m_iterationOffset = -1; + QStringList m_iterationContextIds; }; } // namespace Internal |