Skip to content

Commit 80d64e8

Browse files
authored
Merge branch 'cppcheck-opensource:main' into fixrecheckingui
2 parents 5903177 + 0873197 commit 80d64e8

9 files changed

Lines changed: 71 additions & 4 deletions

lib/checkio.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,8 @@ void CheckIOImpl::checkFileUsage()
155155
tok = tok->linkAt(1);
156156
continue;
157157
}
158+
if (tok->function() && tok->function()->nestedIn)
159+
continue;
158160
if (tok->str() == "{")
159161
indent++;
160162
else if (tok->str() == "}") {
@@ -841,6 +843,8 @@ void CheckIOImpl::checkFormatString(const Token * const tok,
841843
}
842844
++i;
843845
}
846+
while (!width.empty() && width[0] == '0')
847+
width = width.substr(1);
844848
auto bracketBeg = formatString.cend();
845849
if (i != formatString.cend() && *i == '[') {
846850
bracketBeg = i;

lib/tokenize.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -589,12 +589,27 @@ namespace {
589589
}
590590
}
591591

592+
const auto checkForRecursion = [this]() {
593+
if (Token::Match(mTypedefToken, "typedef %name% %name% ;"))
594+
return;
595+
for (const Token *tok = mTypedefToken; tok != mEndToken; tok = tok->next()) {
596+
if (tok == mNameToken)
597+
continue;
598+
if (tok->str() != mNameToken->str())
599+
continue;
600+
if (Token::Match(tok->previous(), "struct|class|enum|union"))
601+
continue;
602+
throw InternalError(tok, "recursive typedef encountered");
603+
}
604+
};
605+
592606
for (Token* type = start; Token::Match(type, "%name%|*|&|&&"); type = type->next()) {
593607
if (type != start && Token::Match(type, "%name% ;") && !type->isStandardType()) {
594608
mRangeType.first = start;
595609
mRangeType.second = type;
596610
mNameToken = type;
597611
mEndToken = mNameToken->next();
612+
checkForRecursion();
598613
return;
599614
}
600615
if (type != start && Token::Match(type, "%name% [")) {
@@ -609,6 +624,7 @@ namespace {
609624
mEndToken = end->next();
610625
mRangeAfterVar.first = mNameToken->next();
611626
mRangeAfterVar.second = mEndToken;
627+
checkForRecursion();
612628
return;
613629
}
614630
if (Token::Match(type->next(), "( * const| %name% ) (") && Token::simpleMatch(type->linkAt(1)->linkAt(1), ") ;")) {
@@ -618,6 +634,7 @@ namespace {
618634
mRangeType.second = mNameToken;
619635
mRangeAfterVar.first = mNameToken->next();
620636
mRangeAfterVar.second = mEndToken;
637+
checkForRecursion();
621638
return;
622639
}
623640
if (type != start && Token::Match(type, "%name% ( !!(") && Token::simpleMatch(type->linkAt(1), ") ;") && !type->isStandardType()) {
@@ -627,6 +644,7 @@ namespace {
627644
mRangeType.second = type;
628645
mRangeAfterVar.first = mNameToken->next();
629646
mRangeAfterVar.second = mEndToken;
647+
checkForRecursion();
630648
return;
631649
}
632650
}

lib/tokenlist.cpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1947,6 +1947,9 @@ void TokenList::validateAst(bool print) const
19471947
if ((tok->isAssignmentOp() || tok->isComparisonOp() || Token::Match(tok,"[|^/%]")) && tok->astOperand1() && !tok->astOperand2())
19481948
throw InternalError(tok, "Syntax Error: AST broken, binary operator has only one operand.", InternalError::AST);
19491949

1950+
if (!(tok->astOperand1() && tok->astOperand2()) && ((isC() && tok->str() == "&&") || Token::Match(tok, "%or%|%oror%")))
1951+
throw InternalError(tok, "Syntax Error: AST broken, binary operator is missing operand(s).", InternalError::AST);
1952+
19501953
// Syntax error if we encounter "?" with operand2 that is not ":"
19511954
if (tok->str() == "?") {
19521955
if (!tok->astOperand1() || !tok->astOperand2())
@@ -2029,9 +2032,9 @@ void TokenList::validateAst(bool print) const
20292032
"' doesn't have two operands.",
20302033
InternalError::AST);
20312034
}
2032-
if (tok->str() == "case" && !tok->astOperand1()) {
2035+
if (!tok->astOperand1() && Token::Match(tok, "case|!")) {
20332036
throw InternalError(tok,
2034-
"Syntax Error: AST broken, 'case' doesn't have an operand.",
2037+
"Syntax Error: AST broken, '" + tok->str() + "' doesn't have an operand.",
20352038
InternalError::AST);
20362039
}
20372040

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
i(){!!:!=!&&d}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
n(f=n){n&&,n}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
typedef const v*v,*;

test/testio.cpp

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ class TestIO : public TestFixture {
5353
TEST_CASE(testScanf3); // #3494
5454
TEST_CASE(testScanf4); // #ticket 2553
5555
TEST_CASE(testScanf5); // #10632
56+
TEST_CASE(testScanf6);
5657

5758
mNewTemplate = false;
5859
TEST_CASE(testScanfArgument);
@@ -693,6 +694,23 @@ class TestIO : public TestFixture {
693694
" fwrite(X::data(), sizeof(char), buffer.size(), d->file);\n"
694695
"}");
695696
ASSERT_EQUALS("[test.cpp:9:5]: (error) Read and write operations without a call to a positioning function (fseek, fsetpos or rewind) or fflush in between result in undefined behaviour. [IOWithoutPositioning]\n", errout_str());
697+
698+
check("struct MemStream {\n"
699+
" char buf[1024];\n"
700+
" int pos = 0;\n"
701+
" void fwrite(const void *ptr, size_t n) { memcpy(buf + pos, ptr, n); pos += (int)n; }\n"
702+
"};\n"
703+
"struct FileStream {\n"
704+
" FILE *fp;\n"
705+
" size_t _fread(void *ptr, size_t n) { return ::fread(ptr, 1, n, fp); }\n"
706+
" size_t fread(void *ptr, size_t n) { return _fread(ptr, n); }\n"
707+
" void copy_to(MemStream *dst, size_t n) {\n"
708+
" char tmp[256];\n"
709+
" fread(tmp, n);\n"
710+
" dst->fwrite(tmp, n);\n"
711+
" }\n"
712+
"};\n");
713+
ASSERT_EQUALS("", errout_str());
696714
}
697715

698716
void seekOnAppendedFile() {
@@ -892,6 +910,14 @@ class TestIO : public TestFixture {
892910
"[test.cpp:3:5]: (error) Width 42 given in format string (no. 2) is larger than destination buffer 's2[42]', use %41[a-z] to prevent overflowing it. [invalidScanfFormatWidth]\n", errout_str());
893911
}
894912

913+
void testScanf6() {
914+
ASSERT_NO_THROW(check("int f(const char *p) {\n"
915+
" char a[3];\n"
916+
" return sscanf(p, \"%02s\", a);\n"
917+
"}\n"));
918+
ASSERT_EQUALS("", errout_str());
919+
}
920+
895921

896922
#define TEST_SCANF_CODE(format, type) \
897923
"void f(){" type " x; scanf(\"" format "\", &x);}"

test/testsimplifytypedef.cpp

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -233,6 +233,7 @@ class TestSimplifyTypedef : public TestFixture {
233233
TEST_CASE(simplifyTypedef160);
234234
TEST_CASE(simplifyTypedef161);
235235
TEST_CASE(simplifyTypedef162);
236+
TEST_CASE(simplifyTypedef163);
236237

237238
TEST_CASE(simplifyTypedefFunction1);
238239
TEST_CASE(simplifyTypedefFunction2); // ticket #1685
@@ -3836,11 +3837,11 @@ class TestSimplifyTypedef : public TestFixture {
38363837
"}";
38373838
ASSERT_EQUALS(exp, tok(code));
38383839

3839-
const char code2[] = "typedef stuct T* T;\n" // #14669
3840+
const char code2[] = "typedef struct T* T;\n" // #14669
38403841
"struct T {\n"
38413842
" T p;\n"
38423843
"};\n";
3843-
const char exp2[] = "struct T { stuct T * p ; } ;";
3844+
const char exp2[] = "struct T { struct T * p ; } ;";
38443845
ASSERT_EQUALS(exp2, simplifyTypedefC(code2));
38453846
}
38463847

@@ -3868,6 +3869,11 @@ class TestSimplifyTypedef : public TestFixture {
38683869
ASSERT_EQUALS(exp, tok(code));
38693870
}
38703871

3872+
void simplifyTypedef163() {
3873+
const char code[] = "typedef v *v;";
3874+
ASSERT_THROW_INTERNAL(tok(code), INTERNAL);
3875+
}
3876+
38713877
void simplifyTypedefFunction1() {
38723878
{
38733879
const char code[] = "typedef void (*my_func)();\n"

test/testtokenize.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@ class TestTokenizer : public TestFixture {
9292
TEST_CASE(tokenize40); // #13181
9393
TEST_CASE(tokenize41); // #13847
9494
TEST_CASE(tokenize42); // #13861
95+
TEST_CASE(tokenize43); // #13861
9596

9697
TEST_CASE(validate);
9798

@@ -941,6 +942,12 @@ class TestTokenizer : public TestFixture {
941942
(void)errout_str();
942943
}
943944

945+
void tokenize43() {
946+
const char code[] = "void f(int i) { do if (i &= 1) {} while (0); }";
947+
ASSERT_NO_THROW(tokenizeAndStringify(code));
948+
(void)errout_str();
949+
}
950+
944951
void validate() {
945952
// C++ code in C file
946953
ASSERT_THROW_INTERNAL(tokenizeAndStringify(";using namespace std;",dinit(TokenizeOptions, $.expand = false, $.cpp = false)), SYNTAX);

0 commit comments

Comments
 (0)