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>
This commit is contained in:
David Schulz
2018-02-28 13:30:42 +01:00
parent 2c89829de4
commit a0cb9919f3
5 changed files with 26 additions and 7 deletions

View File

@@ -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