Skip to content

Commit 3466bdc

Browse files
Fix #13163 fuzzing crash in getEnumType() (danmar#6850)
1 parent 9766474 commit 3466bdc

File tree

8 files changed

+35
-22
lines changed

8 files changed

+35
-22
lines changed

lib/symboldatabase.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -123,18 +123,18 @@ static bool isExecutableScope(const Token* tok)
123123
return false;
124124
}
125125

126-
static bool isEnumDefinition(const Token* tok)
126+
const Token* SymbolDatabase::isEnumDefinition(const Token* tok)
127127
{
128-
if (!Token::Match(tok, "enum class| %name% {|:"))
129-
return false;
128+
if (!Token::Match(tok, "enum class| %name%| {|:"))
129+
return nullptr;
130130
while (!Token::Match(tok, "[{:]"))
131131
tok = tok->next();
132132
if (tok->str() == "{")
133-
return true;
133+
return tok;
134134
tok = tok->next(); // skip ':'
135135
while (Token::Match(tok, "%name%|::"))
136136
tok = tok->next();
137-
return Token::simpleMatch(tok, "{");
137+
return Token::simpleMatch(tok, "{") ? tok : nullptr;
138138
}
139139

140140
void SymbolDatabase::createSymbolDatabaseFindAllScopes()

lib/symboldatabase.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1409,6 +1409,9 @@ class CPPCHECKLIB SymbolDatabase {
14091409
void clangSetVariables(const std::vector<const Variable *> &variableList);
14101410
void createSymbolDatabaseExprIds();
14111411

1412+
/* returns the opening { if tok points to enum */
1413+
static const Token* isEnumDefinition(const Token* tok);
1414+
14121415
private:
14131416
friend class Scope;
14141417
friend class Function;

lib/tokenize.cpp

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8608,8 +8608,16 @@ void Tokenizer::findGarbageCode() const
86088608
syntaxError(tok2, "Unexpected token '" + (tok2 ? tok2->str() : "") + "'");
86098609
}
86108610
}
8611-
if (Token::Match(tok, "enum : %num%| {"))
8612-
syntaxError(tok->tokAt(2), "Unexpected token '" + tok->strAt(2) + "'");
8611+
if (tok->str() == "enum") {
8612+
if (Token::Match(tok->next(), ": %num%| {"))
8613+
syntaxError(tok->tokAt(2), "Unexpected token '" + tok->strAt(2) + "'");
8614+
if (const Token* start = SymbolDatabase::isEnumDefinition(tok)) {
8615+
for (const Token* tok2 = start->next(); tok2 && tok2 != start->link(); tok2 = tok2->next()) {
8616+
if (tok2->str() == ";")
8617+
syntaxError(tok2);
8618+
}
8619+
}
8620+
}
86138621
}
86148622

86158623
// Keywords in global scope
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
enum{C={;}=e};

test/testsimplifytemplate.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3585,7 +3585,7 @@ class TestSimplifyTemplate : public TestFixture {
35853585
"using A2 = struct B2 { void f(T){} };\n"
35863586
"A2<bool> a2;\n"
35873587
"template<class T>\n"
3588-
"using A3 = enum B3 {b = 0;};\n"
3588+
"using A3 = enum B3 {b = 0};\n"
35893589
"A3<int> a3;";
35903590
const char exp[] = "template < int N > "
35913591
"using A1 = struct B1 { static auto constexpr value = N ; } ; "
@@ -3594,7 +3594,7 @@ class TestSimplifyTemplate : public TestFixture {
35943594
"using A2 = struct B2 { void f ( T ) { } } ; "
35953595
"A2 < bool > a2 ; "
35963596
"template < class T > "
3597-
"using A3 = enum B3 { b = 0 ; } ; "
3597+
"using A3 = enum B3 { b = 0 } ; "
35983598
"A3 < int > a3 ;";
35993599
ASSERT_EQUALS(exp, tok(code));
36003600
}

test/testsimplifytypedef.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3353,8 +3353,8 @@ class TestSimplifyTypedef : public TestFixture {
33533353
" struct S { enum E { E0 }; };\n"
33543354
"}\n"
33553355
"typedef N::S T;\n"
3356-
"enum class E { a = T::E0; };\n";
3357-
ASSERT_EQUALS("namespace N { struct S { enum E { E0 } ; } ; } enum class E { a = N :: S :: E0 ; } ;", tok(code));
3356+
"enum class E { a = T::E0 };\n";
3357+
ASSERT_EQUALS("namespace N { struct S { enum E { E0 } ; } ; } enum class E { a = N :: S :: E0 } ;", tok(code));
33583358
}
33593359
{ // #11494
33603360
const char code[] = "typedef struct S {} KEY;\n"

test/testtokenize.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7132,6 +7132,7 @@ class TestTokenizer : public TestFixture {
71327132

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

71367137
ASSERT_THROW_INTERNAL_EQUALS(tokenizeAndStringify("int a() { b((c)return 0) }"), SYNTAX, "syntax error");
71377138
ASSERT_THROW_EQUALS(tokenizeAndStringify("int f() { MACRO(x) return 0; }"),

test/testvarid.cpp

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3838,63 +3838,63 @@ class TestVarID : public TestFixture {
38383838
void varidenum1() {
38393839
const char code[] = "const int eStart = 6;\n"
38403840
"enum myEnum {\n"
3841-
" A = eStart;\n"
3841+
" A = eStart\n"
38423842
"};\n";
38433843
const char expected[] = "1: const int eStart@1 = 6 ;\n"
38443844
"2: enum myEnum {\n"
3845-
"3: A = eStart@1 ;\n"
3845+
"3: A = eStart@1\n"
38463846
"4: } ;\n";
38473847
ASSERT_EQUALS(expected, tokenize(code));
38483848
}
38493849

38503850
void varidenum2() {
38513851
const char code[] = "const int eStart = 6;\n"
38523852
"enum myEnum {\n"
3853-
" A = f(eStart);\n"
3853+
" A = f(eStart)\n"
38543854
"};\n";
38553855
const char expected[] = "1: const int eStart@1 = 6 ;\n"
38563856
"2: enum myEnum {\n"
3857-
"3: A = f ( eStart@1 ) ;\n"
3857+
"3: A = f ( eStart@1 )\n"
38583858
"4: } ;\n";
38593859
ASSERT_EQUALS(expected, tokenize(code));
38603860
}
38613861

38623862
void varidenum3() {
38633863
const char code[] = "const int eStart = 6;\n"
38643864
"enum myEnum {\n"
3865-
" A = f(eStart, x);\n"
3865+
" A = f(eStart, x)\n"
38663866
"};\n";
38673867
const char expected[] = "1: const int eStart@1 = 6 ;\n"
38683868
"2: enum myEnum {\n"
3869-
"3: A = f ( eStart@1 , x ) ;\n"
3869+
"3: A = f ( eStart@1 , x )\n"
38703870
"4: } ;\n";
38713871
ASSERT_EQUALS(expected, tokenize(code));
38723872
}
38733873

38743874
void varidenum4() {
38753875
const char code[] = "const int eStart = 6;\n"
38763876
"enum myEnum {\n"
3877-
" A = f(x, eStart);\n"
3877+
" A = f(x, eStart)\n"
38783878
"};\n";
38793879
const char expected[] = "1: const int eStart@1 = 6 ;\n"
38803880
"2: enum myEnum {\n"
3881-
"3: A = f ( x , eStart@1 ) ;\n"
3881+
"3: A = f ( x , eStart@1 )\n"
38823882
"4: } ;\n";
38833883
ASSERT_EQUALS(expected, tokenize(code));
38843884
}
38853885

38863886
void varidenum5() {
38873887
const char code[] = "const int eStart = 6;\n"
38883888
"enum myEnum {\n"
3889-
" A = f(x, eStart, y);\n"
3889+
" A = f(x, eStart, y)\n"
38903890
"};\n";
38913891
const char expected[] = "1: const int eStart@1 = 6 ;\n"
38923892
"2: enum myEnum {\n"
3893-
"3: A = f ( x , eStart@1 , y ) ;\n"
3893+
"3: A = f ( x , eStart@1 , y )\n"
38943894
"4: } ;\n";
38953895
const char current[] = "1: const int eStart@1 = 6 ;\n"
38963896
"2: enum myEnum {\n"
3897-
"3: A = f ( x , eStart , y ) ;\n"
3897+
"3: A = f ( x , eStart , y )\n"
38983898
"4: } ;\n";
38993899
TODO_ASSERT_EQUALS(expected, current, tokenize(code));
39003900
}

0 commit comments

Comments
 (0)