forked from qt-creator/qt-creator
C++: Fix crash with invalid raw string literal
While parsing a document Bind::asStringLiteral() Token::spell() was called for a raw string literal token with a Token::literal nullptr. This is due scanRawStringLiteral() not properly aborting for invalid/incomplete code and that the code paths handling multi-line-raw-strings were not limited to the highlighting case. Address both cases. Task-number: QTCREATORBUG-18941 Change-Id: I489d288ccbd7b59be396dada846613ff555436cf Reviewed-by: Eike Ziller <eike.ziller@qt.io> Reviewed-by: Orgad Shaneh <orgads@gmail.com>
This commit is contained in:
16
src/libs/3rdparty/cplusplus/Lexer.cpp
vendored
16
src/libs/3rdparty/cplusplus/Lexer.cpp
vendored
@@ -211,7 +211,7 @@ void Lexer::scan_helper(Token *tok)
|
|||||||
_state = 0;
|
_state = 0;
|
||||||
scanCppComment(originalKind);
|
scanCppComment(originalKind);
|
||||||
return;
|
return;
|
||||||
} else if (isRawStringLiteral(s._tokenKind)) {
|
} else if (!control() && isRawStringLiteral(s._tokenKind)) {
|
||||||
tok->f.kind = s._tokenKind;
|
tok->f.kind = s._tokenKind;
|
||||||
if (scanUntilRawStringLiteralEndSimple())
|
if (scanUntilRawStringLiteralEndSimple())
|
||||||
_state = 0;
|
_state = 0;
|
||||||
@@ -755,13 +755,17 @@ void Lexer::scanRawStringLiteral(Token *tok, unsigned char hint)
|
|||||||
yyinp();
|
yyinp();
|
||||||
} else if (_yychar == ')') {
|
} else if (_yychar == ')') {
|
||||||
yyinp();
|
yyinp();
|
||||||
if (delimLength == -1)
|
if (delimLength == -1) {
|
||||||
break;
|
tok->f.kind = T_ERROR;
|
||||||
|
return;
|
||||||
|
}
|
||||||
closingDelimCandidate = _currentChar;
|
closingDelimCandidate = _currentChar;
|
||||||
} else {
|
} else {
|
||||||
if (delimLength == -1) {
|
if (delimLength == -1) {
|
||||||
if (_yychar == '\\' || std::isspace(_yychar))
|
if (_yychar == '\\' || std::isspace(_yychar)) {
|
||||||
break;
|
tok->f.kind = T_ERROR;
|
||||||
|
return;
|
||||||
|
}
|
||||||
yyinp();
|
yyinp();
|
||||||
} else {
|
} else {
|
||||||
if (!closingDelimCandidate) {
|
if (!closingDelimCandidate) {
|
||||||
@@ -804,7 +808,7 @@ void Lexer::scanRawStringLiteral(Token *tok, unsigned char hint)
|
|||||||
else
|
else
|
||||||
tok->f.kind = T_RAW_STRING_LITERAL;
|
tok->f.kind = T_RAW_STRING_LITERAL;
|
||||||
|
|
||||||
if (!closed)
|
if (!control() && !closed)
|
||||||
s._tokenKind = tok->f.kind;
|
s._tokenKind = tok->f.kind;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -366,6 +366,14 @@ void tst_SimpleLexer::literals_data()
|
|||||||
<< T_RAW_STRING_LITERAL
|
<< T_RAW_STRING_LITERAL
|
||||||
;
|
;
|
||||||
QTest::newRow("raw-string-literals") << source << expectedTokenKindList;
|
QTest::newRow("raw-string-literals") << source << expectedTokenKindList;
|
||||||
|
|
||||||
|
source = "R\"\\" ;
|
||||||
|
expectedTokenKindList = TokenKindList() << T_ERROR;
|
||||||
|
QTest::newRow("invalid-raw-string-literals1") << source << expectedTokenKindList;
|
||||||
|
|
||||||
|
source = "R\")" ;
|
||||||
|
expectedTokenKindList = TokenKindList() << T_ERROR;
|
||||||
|
QTest::newRow("invalid-raw-string-literals2") << source << expectedTokenKindList;
|
||||||
}
|
}
|
||||||
|
|
||||||
void tst_SimpleLexer::preprocessor()
|
void tst_SimpleLexer::preprocessor()
|
||||||
|
@@ -48,6 +48,8 @@ private slots:
|
|||||||
void astPathOnGeneratedTokens();
|
void astPathOnGeneratedTokens();
|
||||||
|
|
||||||
void typeMatcher();
|
void typeMatcher();
|
||||||
|
|
||||||
|
void doNotCrashForInvalidRawString();
|
||||||
};
|
};
|
||||||
|
|
||||||
void tst_Misc::diagnosticClient_error()
|
void tst_Misc::diagnosticClient_error()
|
||||||
@@ -266,5 +268,16 @@ void tst_Misc::typeMatcher()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void tst_Misc::doNotCrashForInvalidRawString()
|
||||||
|
{
|
||||||
|
const QByteArray src("\n"
|
||||||
|
"void f() { enum { Size = sizeof(R\"[^\\s]+([^]+)*\") }; }"
|
||||||
|
"}\n"
|
||||||
|
);
|
||||||
|
Document::Ptr doc = Document::create("crash");
|
||||||
|
doc->setUtf8Source(src);
|
||||||
|
doc->check();
|
||||||
|
}
|
||||||
|
|
||||||
QTEST_MAIN(tst_Misc)
|
QTEST_MAIN(tst_Misc)
|
||||||
#include "tst_misc.moc"
|
#include "tst_misc.moc"
|
||||||
|
Reference in New Issue
Block a user