Commit fe0a0918 authored by Nikolai Kosjar's avatar Nikolai Kosjar

C++: Fix use-after-free crash when handling auto expressions

The Control of the Document "exprDoc" in ResolveExpression::visit(
SimpleNameAST*ast) owns names that are passed on further as part of the
LookupItems. However, the life time of that Document and thus the
Control ends in that function.

Fix by using the appropriate Control object.

Task-number: QTCREATORBUG-16731
Change-Id: I5a7af0a67613fff79f7e07865801585c13bb9b45
Reviewed-by: Orgad Shaneh's avatarOrgad Shaneh <orgads@gmail.com>
parent d3f725f3
......@@ -286,8 +286,10 @@ Document::~Document()
{
delete _translationUnit;
_translationUnit = 0;
delete _control->diagnosticClient();
delete _control;
if (_control) {
delete _control->diagnosticClient();
delete _control;
}
_control = 0;
}
......@@ -296,6 +298,25 @@ Control *Document::control() const
return _control;
}
Control *Document::swapControl(Control *newControl)
{
if (newControl) {
const StringLiteral *fileId = newControl->stringLiteral(_translationUnit->fileId()->chars(),
_translationUnit->fileId()->size());
const auto newTranslationUnit = new TranslationUnit(newControl, fileId);
newTranslationUnit->setLanguageFeatures(_translationUnit->languageFeatures());
delete _translationUnit;
_translationUnit = newTranslationUnit;
} else {
delete _translationUnit;
_translationUnit = 0;
}
Control *oldControl = _control;
_control = newControl;
return oldControl;
}
unsigned Document::revision() const
{
return _revision;
......@@ -696,7 +717,8 @@ void Document::releaseSourceAndAST()
if (!_keepSourceAndASTCount.deref()) {
_source.clear();
_translationUnit->release();
_control->squeeze();
if (_control)
_control->squeeze();
}
}
......
......@@ -78,6 +78,7 @@ public:
unsigned bytesOffset, unsigned utf16charsOffset);
Control *control() const;
Control *swapControl(Control *newControl);
TranslationUnit *translationUnit() const;
bool skipFunctionBody() const;
......
......@@ -688,6 +688,31 @@ public:
bool _block;
};
class ExpressionDocumentHelper
{
public:
// Set up an expression document with an external Control
ExpressionDocumentHelper(const QByteArray &utf8code, Control *control)
: document(Document::create(QLatin1String("<completion>")))
{
Control *oldControl = document->swapControl(control);
delete oldControl->diagnosticClient();
delete oldControl;
document->setUtf8Source(utf8code);
document->parse(Document::ParseExpression);
document->check();
}
// Ensure that the external Control is not deleted
~ExpressionDocumentHelper()
{
document->swapControl(nullptr);
}
public:
Document::Ptr document;
};
} // namespace anonymous
bool ResolveExpression::visit(SimpleNameAST *ast)
......@@ -730,9 +755,9 @@ bool ResolveExpression::visit(SimpleNameAST *ast)
exprTyper.init(doc, _context.snapshot(), _context.bindings(),
QSet<const Declaration* >(_autoDeclarationsBeingResolved) << decl);
Document::Ptr exprDoc =
documentForExpression(exprTyper.preprocessedExpression(initializer));
exprDoc->check();
const ExpressionDocumentHelper exprHelper(exprTyper.preprocessedExpression(initializer),
_context.bindings()->control().data());
const Document::Ptr exprDoc = exprHelper.document;
DeduceAutoCheck deduceAuto(ast->name->identifier(), exprDoc->translationUnit());
if (deduceAuto._block)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment