From 76006a1353f1282a940bf80a523b93ead7beae93 Mon Sep 17 00:00:00 2001 From: Nikolai Kosjar Date: Tue, 19 Sep 2017 14:36:21 +0200 Subject: 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 Reviewed-by: Orgad Shaneh --- src/libs/3rdparty/cplusplus/Lexer.cpp | 16 ++++++++++------ tests/auto/cplusplus/lexer/tst_lexer.cpp | 8 ++++++++ tests/auto/cplusplus/misc/tst_misc.cpp | 13 +++++++++++++ 3 files changed, 31 insertions(+), 6 deletions(-) diff --git a/src/libs/3rdparty/cplusplus/Lexer.cpp b/src/libs/3rdparty/cplusplus/Lexer.cpp index e62c9412a4..079ae0ca6e 100644 --- a/src/libs/3rdparty/cplusplus/Lexer.cpp +++ b/src/libs/3rdparty/cplusplus/Lexer.cpp @@ -211,7 +211,7 @@ void Lexer::scan_helper(Token *tok) _state = 0; scanCppComment(originalKind); return; - } else if (isRawStringLiteral(s._tokenKind)) { + } else if (!control() && isRawStringLiteral(s._tokenKind)) { tok->f.kind = s._tokenKind; if (scanUntilRawStringLiteralEndSimple()) _state = 0; @@ -755,13 +755,17 @@ void Lexer::scanRawStringLiteral(Token *tok, unsigned char hint) yyinp(); } else if (_yychar == ')') { yyinp(); - if (delimLength == -1) - break; + if (delimLength == -1) { + tok->f.kind = T_ERROR; + return; + } closingDelimCandidate = _currentChar; } else { if (delimLength == -1) { - if (_yychar == '\\' || std::isspace(_yychar)) - break; + if (_yychar == '\\' || std::isspace(_yychar)) { + tok->f.kind = T_ERROR; + return; + } yyinp(); } else { if (!closingDelimCandidate) { @@ -804,7 +808,7 @@ void Lexer::scanRawStringLiteral(Token *tok, unsigned char hint) else tok->f.kind = T_RAW_STRING_LITERAL; - if (!closed) + if (!control() && !closed) s._tokenKind = tok->f.kind; } diff --git a/tests/auto/cplusplus/lexer/tst_lexer.cpp b/tests/auto/cplusplus/lexer/tst_lexer.cpp index a2c415d33c..1721efaedd 100644 --- a/tests/auto/cplusplus/lexer/tst_lexer.cpp +++ b/tests/auto/cplusplus/lexer/tst_lexer.cpp @@ -366,6 +366,14 @@ void tst_SimpleLexer::literals_data() << T_RAW_STRING_LITERAL ; 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() diff --git a/tests/auto/cplusplus/misc/tst_misc.cpp b/tests/auto/cplusplus/misc/tst_misc.cpp index aff5a12ce0..808408df40 100644 --- a/tests/auto/cplusplus/misc/tst_misc.cpp +++ b/tests/auto/cplusplus/misc/tst_misc.cpp @@ -48,6 +48,8 @@ private slots: void astPathOnGeneratedTokens(); void typeMatcher(); + + void doNotCrashForInvalidRawString(); }; 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) #include "tst_misc.moc" -- cgit v1.2.1