aboutsummaryrefslogtreecommitdiffstats
path: root/src/plugins/texteditor/generichighlighter
diff options
context:
space:
mode:
authorDaniel Levin <dendy.ua@gmail.com>2018-10-31 03:45:42 -0700
committerDaniel Levin <dendy.ua@gmail.com>2018-11-08 08:29:50 +0000
commit68e780f99ddb26cd35c5d3cbcf79d59fae663c24 (patch)
tree984d19a0e903b66f079c09d9a78e591ae2515781 /src/plugins/texteditor/generichighlighter
parentd84672226447259166fb2f897ca1915b8b234ba5 (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')
-rw-r--r--src/plugins/texteditor/generichighlighter/highlighter.cpp7
-rw-r--r--src/plugins/texteditor/generichighlighter/progressdata.cpp15
-rw-r--r--src/plugins/texteditor/generichighlighter/progressdata.h4
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