summaryrefslogtreecommitdiff
path: root/src/plugins/texteditor
diff options
context:
space:
mode:
authorDavid Schulz <david.schulz@qt.io>2018-02-28 13:30:42 +0100
committerDavid Schulz <david.schulz@qt.io>2018-02-28 12:55:00 +0000
commita0cb9919f32d8efa26fe3d3c13b8427859049dcc (patch)
treed09226305c07e4cf17ca8dd7cd6d86e3c614b25b /src/plugins/texteditor
parent2c89829de4136303cfa5ea510fd1ad05e4e8fd42 (diff)
downloadqt-creator-a0cb9919f32d8efa26fe3d3c13b8427859049dcc.tar.gz
Highlighter: fix crash after context change
Context changes might delete rules. Make sure to not dereference these deleted rules by: - save needed rule information before context change - untrack every rule in ProgressData that was deleted Task-number: QTCREATORBUG-19916 Change-Id: Icdbb739c1030bf918dbbe6c3a540a7c8893ce5a9 Reviewed-by: Christian Stenger <christian.stenger@qt.io>
Diffstat (limited to 'src/plugins/texteditor')
-rw-r--r--src/plugins/texteditor/generichighlighter/highlighter.cpp16
-rw-r--r--src/plugins/texteditor/generichighlighter/progressdata.cpp5
-rw-r--r--src/plugins/texteditor/generichighlighter/progressdata.h1
-rw-r--r--src/plugins/texteditor/generichighlighter/specificrules.cpp8
-rw-r--r--src/plugins/texteditor/generichighlighter/specificrules.h3
5 files changed, 26 insertions, 7 deletions
diff --git a/src/plugins/texteditor/generichighlighter/highlighter.cpp b/src/plugins/texteditor/generichighlighter/highlighter.cpp
index 2902f09a63..fd875eae28 100644
--- a/src/plugins/texteditor/generichighlighter/highlighter.cpp
+++ b/src/plugins/texteditor/generichighlighter/highlighter.cpp
@@ -372,29 +372,33 @@ void Highlighter::iterateThroughRules(const QString &text,
progress->clearBracesMatches();
}
+ const QString itemData = rule->itemData();
+ const QSharedPointer<HighlightDefinition> definition = rule->definition();
+ const bool lookAhead = rule->isLookAhead();
if (progress->isWillContinueLine()) {
createWillContinueBlock();
progress->setWillContinueLine(false);
} else {
if (rule->hasChildren())
iterateThroughRules(text, length, progress, true, rule->children());
-
if (!rule->context().isEmpty() && contextChangeRequired(rule->context())) {
m_currentCaptures = progress->captures();
- changeContext(rule->context(), rule->definition());
+ changeContext(rule->context(), definition);
contextChanged = true;
}
}
+ // Do NOT access rule frome here on, because a context change might delete rule
+
// Format is not applied to child rules directly (but relative to the offset of their
// parent) nor to look ahead rules.
- if (!childRule && !rule->isLookAhead()) {
- if (rule->itemData().isEmpty())
+ if (!childRule && !lookAhead) {
+ if (itemData.isEmpty())
applyFormat(startOffset, progress->offset() - startOffset,
m_currentContext->itemData(), m_currentContext->definition());
else
- applyFormat(startOffset, progress->offset() - startOffset, rule->itemData(),
- rule->definition());
+ applyFormat(startOffset, progress->offset() - startOffset, itemData,
+ definition);
}
// When there is a match of one child rule the others should be skipped. Otherwise
diff --git a/src/plugins/texteditor/generichighlighter/progressdata.cpp b/src/plugins/texteditor/generichighlighter/progressdata.cpp
index 6075a1a4e4..d79d5b0152 100644
--- a/src/plugins/texteditor/generichighlighter/progressdata.cpp
+++ b/src/plugins/texteditor/generichighlighter/progressdata.cpp
@@ -108,3 +108,8 @@ void ProgressData::trackRule(Rule *rule)
{
m_trackedRules.append(rule);
}
+
+void ProgressData::unTrackRule(Rule *rule)
+{
+ m_trackedRules.removeAll(rule);
+}
diff --git a/src/plugins/texteditor/generichighlighter/progressdata.h b/src/plugins/texteditor/generichighlighter/progressdata.h
index 9563a1601e..d2b158146d 100644
--- a/src/plugins/texteditor/generichighlighter/progressdata.h
+++ b/src/plugins/texteditor/generichighlighter/progressdata.h
@@ -65,6 +65,7 @@ public:
const QStringList &captures() const;
void trackRule(Rule *rule);
+ void unTrackRule(Rule *rule);
private:
int m_offset;
diff --git a/src/plugins/texteditor/generichighlighter/specificrules.cpp b/src/plugins/texteditor/generichighlighter/specificrules.cpp
index 02e5ed4230..8c4b80dc66 100644
--- a/src/plugins/texteditor/generichighlighter/specificrules.cpp
+++ b/src/plugins/texteditor/generichighlighter/specificrules.cpp
@@ -172,6 +172,12 @@ bool StringDetectRule::doMatchSucceed(const QString &text,
}
// RegExpr
+RegExprRule::~RegExprRule()
+{
+ if (m_progress)
+ m_progress->unTrackRule(this);
+}
+
void RegExprRule::setPattern(const QString &pattern)
{
if (pattern.startsWith(QLatin1Char('^')))
@@ -194,6 +200,7 @@ void RegExprRule::doReplaceExpressions(const QStringList &captures)
void RegExprRule::doProgressFinished()
{
+ m_progress = nullptr;
m_isCached = false;
}
@@ -234,6 +241,7 @@ bool RegExprRule::doMatchSucceed(const QString &text,
return true;
m_isCached = true;
+ m_progress = progress;
progress->trackRule(this);
return false;
diff --git a/src/plugins/texteditor/generichighlighter/specificrules.h b/src/plugins/texteditor/generichighlighter/specificrules.h
index 051ab81d26..63beaf8df9 100644
--- a/src/plugins/texteditor/generichighlighter/specificrules.h
+++ b/src/plugins/texteditor/generichighlighter/specificrules.h
@@ -114,7 +114,7 @@ private:
class RegExprRule : public DynamicRule
{
public:
- virtual ~RegExprRule() {}
+ virtual ~RegExprRule();
void setPattern(const QString &pattern);
void setInsensitive(const QString &insensitive);
@@ -136,6 +136,7 @@ private:
int m_length = 0;
QStringList m_captures;
QRegExp m_expression;
+ ProgressData *m_progress = nullptr;
};
class KeywordRule : public Rule