Skip to content

Commit

Permalink
Fix #13163 fuzzing crash in getEnumType() (#6850)
Browse files Browse the repository at this point in the history
  • Loading branch information
chrchr-github authored Oct 2, 2024
1 parent 9766474 commit 3466bdc
Show file tree
Hide file tree
Showing 8 changed files with 35 additions and 22 deletions.
10 changes: 5 additions & 5 deletions lib/symboldatabase.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -123,18 +123,18 @@ static bool isExecutableScope(const Token* tok)
return false;
}

static bool isEnumDefinition(const Token* tok)
const Token* SymbolDatabase::isEnumDefinition(const Token* tok)
{
if (!Token::Match(tok, "enum class| %name% {|:"))
return false;
if (!Token::Match(tok, "enum class| %name%| {|:"))
return nullptr;
while (!Token::Match(tok, "[{:]"))
tok = tok->next();
if (tok->str() == "{")
return true;
return tok;
tok = tok->next(); // skip ':'
while (Token::Match(tok, "%name%|::"))
tok = tok->next();
return Token::simpleMatch(tok, "{");
return Token::simpleMatch(tok, "{") ? tok : nullptr;
}

void SymbolDatabase::createSymbolDatabaseFindAllScopes()
Expand Down
3 changes: 3 additions & 0 deletions lib/symboldatabase.h
Original file line number Diff line number Diff line change
Expand Up @@ -1409,6 +1409,9 @@ class CPPCHECKLIB SymbolDatabase {
void clangSetVariables(const std::vector<const Variable *> &variableList);
void createSymbolDatabaseExprIds();

/* returns the opening { if tok points to enum */
static const Token* isEnumDefinition(const Token* tok);

private:
friend class Scope;
friend class Function;
Expand Down
12 changes: 10 additions & 2 deletions lib/tokenize.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8608,8 +8608,16 @@ void Tokenizer::findGarbageCode() const
syntaxError(tok2, "Unexpected token '" + (tok2 ? tok2->str() : "") + "'");
}
}
if (Token::Match(tok, "enum : %num%| {"))
syntaxError(tok->tokAt(2), "Unexpected token '" + tok->strAt(2) + "'");
if (tok->str() == "enum") {
if (Token::Match(tok->next(), ": %num%| {"))
syntaxError(tok->tokAt(2), "Unexpected token '" + tok->strAt(2) + "'");
if (const Token* start = SymbolDatabase::isEnumDefinition(tok)) {
for (const Token* tok2 = start->next(); tok2 && tok2 != start->link(); tok2 = tok2->next()) {
if (tok2->str() == ";")
syntaxError(tok2);
}
}
}
}

// Keywords in global scope
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
enum{C={;}=e};
4 changes: 2 additions & 2 deletions test/testsimplifytemplate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3585,7 +3585,7 @@ class TestSimplifyTemplate : public TestFixture {
"using A2 = struct B2 { void f(T){} };\n"
"A2<bool> a2;\n"
"template<class T>\n"
"using A3 = enum B3 {b = 0;};\n"
"using A3 = enum B3 {b = 0};\n"
"A3<int> a3;";
const char exp[] = "template < int N > "
"using A1 = struct B1 { static auto constexpr value = N ; } ; "
Expand All @@ -3594,7 +3594,7 @@ class TestSimplifyTemplate : public TestFixture {
"using A2 = struct B2 { void f ( T ) { } } ; "
"A2 < bool > a2 ; "
"template < class T > "
"using A3 = enum B3 { b = 0 ; } ; "
"using A3 = enum B3 { b = 0 } ; "
"A3 < int > a3 ;";
ASSERT_EQUALS(exp, tok(code));
}
Expand Down
4 changes: 2 additions & 2 deletions test/testsimplifytypedef.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3353,8 +3353,8 @@ class TestSimplifyTypedef : public TestFixture {
" struct S { enum E { E0 }; };\n"
"}\n"
"typedef N::S T;\n"
"enum class E { a = T::E0; };\n";
ASSERT_EQUALS("namespace N { struct S { enum E { E0 } ; } ; } enum class E { a = N :: S :: E0 ; } ;", tok(code));
"enum class E { a = T::E0 };\n";
ASSERT_EQUALS("namespace N { struct S { enum E { E0 } ; } ; } enum class E { a = N :: S :: E0 } ;", tok(code));
}
{ // #11494
const char code[] = "typedef struct S {} KEY;\n"
Expand Down
1 change: 1 addition & 0 deletions test/testtokenize.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7132,6 +7132,7 @@ class TestTokenizer : public TestFixture {

ASSERT_THROW_INTERNAL_EQUALS(tokenizeAndStringify("enum : { };"), SYNTAX, "syntax error: Unexpected token '{'");
ASSERT_THROW_INTERNAL_EQUALS(tokenizeAndStringify("enum : 3 { };"), SYNTAX, "syntax error: Unexpected token '3'");
ASSERT_NO_THROW(tokenizeAndStringify("enum { E = int{} };"));

ASSERT_THROW_INTERNAL_EQUALS(tokenizeAndStringify("int a() { b((c)return 0) }"), SYNTAX, "syntax error");
ASSERT_THROW_EQUALS(tokenizeAndStringify("int f() { MACRO(x) return 0; }"),
Expand Down
22 changes: 11 additions & 11 deletions test/testvarid.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3838,63 +3838,63 @@ class TestVarID : public TestFixture {
void varidenum1() {
const char code[] = "const int eStart = 6;\n"
"enum myEnum {\n"
" A = eStart;\n"
" A = eStart\n"
"};\n";
const char expected[] = "1: const int eStart@1 = 6 ;\n"
"2: enum myEnum {\n"
"3: A = eStart@1 ;\n"
"3: A = eStart@1\n"
"4: } ;\n";
ASSERT_EQUALS(expected, tokenize(code));
}

void varidenum2() {
const char code[] = "const int eStart = 6;\n"
"enum myEnum {\n"
" A = f(eStart);\n"
" A = f(eStart)\n"
"};\n";
const char expected[] = "1: const int eStart@1 = 6 ;\n"
"2: enum myEnum {\n"
"3: A = f ( eStart@1 ) ;\n"
"3: A = f ( eStart@1 )\n"
"4: } ;\n";
ASSERT_EQUALS(expected, tokenize(code));
}

void varidenum3() {
const char code[] = "const int eStart = 6;\n"
"enum myEnum {\n"
" A = f(eStart, x);\n"
" A = f(eStart, x)\n"
"};\n";
const char expected[] = "1: const int eStart@1 = 6 ;\n"
"2: enum myEnum {\n"
"3: A = f ( eStart@1 , x ) ;\n"
"3: A = f ( eStart@1 , x )\n"
"4: } ;\n";
ASSERT_EQUALS(expected, tokenize(code));
}

void varidenum4() {
const char code[] = "const int eStart = 6;\n"
"enum myEnum {\n"
" A = f(x, eStart);\n"
" A = f(x, eStart)\n"
"};\n";
const char expected[] = "1: const int eStart@1 = 6 ;\n"
"2: enum myEnum {\n"
"3: A = f ( x , eStart@1 ) ;\n"
"3: A = f ( x , eStart@1 )\n"
"4: } ;\n";
ASSERT_EQUALS(expected, tokenize(code));
}

void varidenum5() {
const char code[] = "const int eStart = 6;\n"
"enum myEnum {\n"
" A = f(x, eStart, y);\n"
" A = f(x, eStart, y)\n"
"};\n";
const char expected[] = "1: const int eStart@1 = 6 ;\n"
"2: enum myEnum {\n"
"3: A = f ( x , eStart@1 , y ) ;\n"
"3: A = f ( x , eStart@1 , y )\n"
"4: } ;\n";
const char current[] = "1: const int eStart@1 = 6 ;\n"
"2: enum myEnum {\n"
"3: A = f ( x , eStart , y ) ;\n"
"3: A = f ( x , eStart , y )\n"
"4: } ;\n";
TODO_ASSERT_EQUALS(expected, current, tokenize(code));
}
Expand Down

0 comments on commit 3466bdc

Please sign in to comment.