From ed4a47de456e460d9574f3290bb0a9cbf5e39693 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Marjam=C3=A4ki?= Date: Fri, 22 Jul 2016 16:54:24 +0200 Subject: [PATCH] Tokenizer: Improve syntax checking of switch,if,while --- lib/tokenize.cpp | 37 +++++++++++++++++++++++++++++++++++++ lib/tokenize.h | 3 +++ test/testgarbage.cpp | 20 ++++++++++---------- test/testnullpointer.cpp | 3 --- test/testother.cpp | 2 +- test/testtokenize.cpp | 19 ++----------------- test/testuninitvar.cpp | 13 ------------- 7 files changed, 53 insertions(+), 44 deletions(-) diff --git a/lib/tokenize.cpp b/lib/tokenize.cpp index 216fdd3c8..f41441f63 100644 --- a/lib/tokenize.cpp +++ b/lib/tokenize.cpp @@ -3469,6 +3469,20 @@ bool Tokenizer::simplifyTokenList1(const char FileName[]) Token::simpleMatch(tok->linkAt(2), "} ;")) { syntaxError(tok); } + + if (tok->str() == "switch") { // switch (EXPR) { ... } + if (!Token::Match(tok->next(), "( !!)")) + syntaxError(tok->next()); + if (!Token::simpleMatch(tok->linkAt(1),") {")) + syntaxError(tok->linkAt(1)); + validateExpr(tok->next(), tok->linkAt(1)); + } + + if (Token::Match(tok, "if|while")) { + if (!Token::Match(tok->next(), "( !!)")) + syntaxError(tok->next()); + validateExpr(tok->next(), tok->linkAt(1)); + } } if (!simplifyAddBraces()) @@ -8175,6 +8189,29 @@ void Tokenizer::validate() const cppcheckError(lastTok); } +void Tokenizer::validateExpr(const Token *start, const Token *end) +{ + std::set controlFlowKeywords; + controlFlowKeywords.insert("goto"); + controlFlowKeywords.insert("do"); + controlFlowKeywords.insert("if"); + controlFlowKeywords.insert("else"); + controlFlowKeywords.insert("for"); + controlFlowKeywords.insert("while"); + controlFlowKeywords.insert("switch"); + controlFlowKeywords.insert("break"); + controlFlowKeywords.insert("continue"); + controlFlowKeywords.insert("return"); + for (const Token *tok = start; tok != end; tok = tok->next()) { + if (controlFlowKeywords.find(tok->str()) != controlFlowKeywords.end()) + syntaxError(tok); + if (tok->str() == ";") + syntaxError(tok); + if (tok->str() == "{") + tok = tok->link(); + } +} + std::string Tokenizer::simplifyString(const std::string &source) { std::string str = source; diff --git a/lib/tokenize.h b/lib/tokenize.h index 2954e090f..e30c8d24b 100644 --- a/lib/tokenize.h +++ b/lib/tokenize.h @@ -592,6 +592,9 @@ private: */ void validate() const; + /** Validate that expression is valid. If it's invalid a syntax error is reported. */ + void validateExpr(const Token *start, const Token *end); + /** * Remove __declspec() */ diff --git a/test/testgarbage.cpp b/test/testgarbage.cpp index 5bfd20637..53e07daf7 100644 --- a/test/testgarbage.cpp +++ b/test/testgarbage.cpp @@ -246,7 +246,7 @@ private: // run alternate check first. It should only ensure stability - so we catch exceptions here. try { checkCodeInternal(code, alternatefilename); - } catch (InternalError&) { + } catch (const InternalError&) { } return checkCodeInternal(code, filename); @@ -451,7 +451,7 @@ private: } void garbageCode15() { // Ticket #5203 - checkCode("int f ( int* r ) { { int s[2] ; f ( s ) ; if ( ) } }"); + ASSERT_THROW(checkCode("int f ( int* r ) { { int s[2] ; f ( s ) ; if ( ) } }"), InternalError); } void garbageCode16() { @@ -480,13 +480,13 @@ private: void garbageCode21() { // Ticket #3486 - Don't crash garbage code - checkCode("void f()\n" - "{\n" - " (\n" - " x;\n" - " int a, a2, a2*x; if () ;\n" - " )\n" - "}"); + ASSERT_THROW(checkCode("void f()\n" + "{\n" + " (\n" + " x;\n" + " int a, a2, a2*x; if () ;\n" + " )\n" + "}"), InternalError); } void garbageCode22() { @@ -765,7 +765,7 @@ private: } void garbageCode76() { // #6754 - checkCode(" ( ) ( ) { ( ) [ ] } TEST ( ) { ( _broadcast_f32x4 ) ( ) ( ) ( ) ( ) if ( ) ( ) ; } E mask = ( ) [ ] ( ) res1.x ="); + ASSERT_THROW(checkCode(" ( ) ( ) { ( ) [ ] } TEST ( ) { ( _broadcast_f32x4 ) ( ) ( ) ( ) ( ) if ( ) ( ) ; } E mask = ( ) [ ] ( ) res1.x ="), InternalError); } void garbageCode77() { // #6755 diff --git a/test/testnullpointer.cpp b/test/testnullpointer.cpp index 68b775f17..5ab8bf742 100644 --- a/test/testnullpointer.cpp +++ b/test/testnullpointer.cpp @@ -1538,9 +1538,6 @@ private: "}"); ASSERT_EQUALS("", errout.str()); - // #2582 - segmentation fault - check("if()"); - // #2674 - different functions check("class Fred {\n" "public:\n" diff --git a/test/testother.cpp b/test/testother.cpp index ccb126dcf..d9043f825 100644 --- a/test/testother.cpp +++ b/test/testother.cpp @@ -3410,7 +3410,7 @@ private: ASSERT_EQUALS("", errout.str()); // make sure there are not "same expression" fp when there are different ({}) expressions - check("void f(long x) { if (({ 1+2; }) == ({3+4};)) {} }"); + check("void f(long x) { if (({ 1+2; }) == ({3+4;})) {} }"); ASSERT_EQUALS("", errout.str()); // #5535: Reference named like its type diff --git a/test/testtokenize.cpp b/test/testtokenize.cpp index 997065a6c..9c97e063e 100644 --- a/test/testtokenize.cpp +++ b/test/testtokenize.cpp @@ -102,16 +102,14 @@ private: TEST_CASE(ifAddBraces3); TEST_CASE(ifAddBraces4); TEST_CASE(ifAddBraces5); - TEST_CASE(ifAddBraces6); TEST_CASE(ifAddBraces7); TEST_CASE(ifAddBraces9); TEST_CASE(ifAddBraces10); TEST_CASE(ifAddBraces11); TEST_CASE(ifAddBraces12); TEST_CASE(ifAddBraces13); - TEST_CASE(ifAddBraces14); // #2610 - segfault: if()<{} TEST_CASE(ifAddBraces15); // #2616 - unknown macro before if - TEST_CASE(ifAddBraces16); // ticket # 2739 (segmentation fault) + TEST_CASE(ifAddBraces16); TEST_CASE(ifAddBraces17); // '} else' should be in the same line TEST_CASE(ifAddBraces18); // #3424 - if if { } else else TEST_CASE(ifAddBraces19); // #3928 - if for if else @@ -1096,11 +1094,6 @@ private: "}", tokenizeAndStringify(code, true)); } - void ifAddBraces6() { - const char code[] = "if()"; - ASSERT_EQUALS("if ( )", tokenizeAndStringify(code, true)); - } - void ifAddBraces7() { const char code[] = "void f()\n" "{\n" @@ -1163,20 +1156,12 @@ private: ASSERT_EQUALS(expected2, tokenizeAndStringify(code2, true)); } - void ifAddBraces14() { - // ticket #2610 (segfault) - tokenizeAndStringify("if()<{}", false); - } - void ifAddBraces15() { // ticket #2616 - unknown macro before if ASSERT_EQUALS("{ A if ( x ) { y ( ) ; } }", tokenizeAndStringify("{A if(x)y();}", false)); } - void ifAddBraces16() { // ticket # 2739 (segmentation fault) - tokenizeAndStringify("if()x"); - ASSERT_EQUALS("", errout.str()); - + void ifAddBraces16() { // ticket #2873 - the fix is not needed anymore. { const char code[] = "void f() { " diff --git a/test/testuninitvar.cpp b/test/testuninitvar.cpp index c4d860d19..7d96b2251 100644 --- a/test/testuninitvar.cpp +++ b/test/testuninitvar.cpp @@ -60,7 +60,6 @@ private: TEST_CASE(uninitvar2_while); TEST_CASE(uninitvar2_4494); // #4494 TEST_CASE(uninitvar2_malloc); // malloc returns uninitialized data - TEST_CASE(uninitvar7); // ticket #5971 TEST_CASE(uninitvar8); // ticket #6230 TEST_CASE(uninitvar9); // ticket #6424 TEST_CASE(uninitvar_unconditionalTry); @@ -2576,18 +2575,6 @@ private: ASSERT_EQUALS("", errout.str()); } - void uninitvar7() { - const char code[] = "void eDBauth_user() {\n" - " char *blid_cert;\n" - " if( ) {\n" - " blid_cert = ;\n" - " } \n" - "}\n"; - - // Assume dfs is a non POD type if file is C++ - checkUninitVar(code, "test.cpp"); - } - void uninitvar8() { const char code[] = "struct Fred {\n" " void Sync(dsmp_t& type, int& len, int limit = 123);\n"