diff options
author | David Schulz <david.schulz@qt.io> | 2018-02-28 13:30:42 +0100 |
---|---|---|
committer | David Schulz <david.schulz@qt.io> | 2018-02-28 12:55:00 +0000 |
commit | a0cb9919f32d8efa26fe3d3c13b8427859049dcc (patch) | |
tree | d09226305c07e4cf17ca8dd7cd6d86e3c614b25b /src/plugins | |
parent | 2c89829de4136303cfa5ea510fd1ad05e4e8fd42 (diff) | |
download | qt-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')
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 |