From 7d4b4919f9d5644f88637833f3dadac633b573f0 Mon Sep 17 00:00:00 2001 From: chrchr Date: Thu, 6 Jul 2023 17:45:05 +0200 Subject: [PATCH 1/4] Fix #11810 nullptr deref in compilePrecedence2() (II) --- lib/tokenize.cpp | 2 +- test/testtokenize.cpp | 16 ++++++++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/lib/tokenize.cpp b/lib/tokenize.cpp index b1a5e7b4093..21efa72c1b3 100644 --- a/lib/tokenize.cpp +++ b/lib/tokenize.cpp @@ -5249,7 +5249,7 @@ void Tokenizer::createLinks2() } else if (token->str() == "<" && ((token->previous() && (token->previous()->isTemplate() || (token->previous()->isName() && !token->previous()->varId()) || - (token->strAt(-1) == "]" && !Token::Match(token->linkAt(-1)->previous(), "%name%|)")))) || + (token->strAt(-1) == "]" && (!Token::Match(token->linkAt(-1)->previous(), "%name%|)") || token->linkAt(-1)->previous()->isKeyword())))) || Token::Match(token->next(), ">|>>"))) { type.push(token); if (token->previous()->str() == "template") diff --git a/test/testtokenize.cpp b/test/testtokenize.cpp index ec0976528e3..3688748c349 100644 --- a/test/testtokenize.cpp +++ b/test/testtokenize.cpp @@ -3515,6 +3515,22 @@ class TestTokenizer : public TestFixture { ASSERT_EQUALS(true, tok1->link() == tok2); ASSERT_EQUALS(true, tok2->link() == tok1); } + + { + const char code[] = "void f() {\n" + " auto g = [] () {\n" + " return [] () {};\n" + " };\n" + "}\n"; + errout.str(""); + Tokenizer tokenizer(&settings0, this); + std::istringstream istr(code); + ASSERT(tokenizer.tokenize(istr, "test.cpp")); + const Token* tok1 = Token::findsimplematch(tokenizer.tokens(), "< T"); + const Token* tok2 = Token::findsimplematch(tok1, "> ("); + ASSERT_EQUALS(true, tok1->link() == tok2); + ASSERT_EQUALS(true, tok2->link() == tok1); + } } void simplifyString() { From 607c090a3cb6d63d199e9bf63fa02aa6a034d583 Mon Sep 17 00:00:00 2001 From: chrchr Date: Fri, 7 Jul 2023 11:48:07 +0200 Subject: [PATCH 2/4] Fix #11819 FP stlcstrConstructor for string_view constructed with size argument --- lib/checkstl.cpp | 2 +- test/teststl.cpp | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/lib/checkstl.cpp b/lib/checkstl.cpp index ceec3cd9b00..ede7460bc1b 100644 --- a/lib/checkstl.cpp +++ b/lib/checkstl.cpp @@ -1992,7 +1992,7 @@ void CheckStl::string_c_str() } } } - } else if (printPerformance && Token::Match(tok, "%var% (|{ %var% . c_str|data ( )") && + } else if (printPerformance && Token::Match(tok, "%var% (|{ %var% . c_str|data ( ) !!,") && tok->variable() && (tok->variable()->isStlStringType() || tok->variable()->isStlStringViewType()) && tok->tokAt(2)->variable() && tok->tokAt(2)->variable()->isStlStringType()) { string_c_strConstructor(tok, tok->variable()->getTypeName()); diff --git a/test/teststl.cpp b/test/teststl.cpp index 77dc8db6bb8..0765d2271dc 100644 --- a/test/teststl.cpp +++ b/test/teststl.cpp @@ -4256,6 +4256,11 @@ class TestStl : public TestFixture { ASSERT_EQUALS("[test.cpp:2]: (performance) Assigning the result of c_str() to a std::string_view is slow and redundant.\n" "[test.cpp:6]: (performance) Constructing a std::string_view from the result of c_str() is slow and redundant.\n", errout.str()); + + check("void f(const std::string& s) {\n" // #11819 + " std::string_view sv(s.data(), 13);\n" + "}\n"); + ASSERT_EQUALS("", errout.str()); } void uselessCalls() { From 1f44fbbeb76d30a052119e67fa58bedfda8e50ac Mon Sep 17 00:00:00 2001 From: chrchr Date: Fri, 7 Jul 2023 11:52:35 +0200 Subject: [PATCH 3/4] Fix #11818 FP constParameterReference with stream write --- lib/astutils.cpp | 2 +- test/testother.cpp | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/lib/astutils.cpp b/lib/astutils.cpp index c3d70d0cfc0..268b9535b1e 100644 --- a/lib/astutils.cpp +++ b/lib/astutils.cpp @@ -3033,7 +3033,7 @@ bool isLikelyStreamRead(bool cpp, const Token *op) const Token *parent = op; while (parent->astParent() && parent->astParent()->str() == op->str()) parent = parent->astParent(); - if (parent->astParent() && !Token::Match(parent->astParent(), "%oror%|&&|(|,|.|!|;")) + if (parent->astParent() && !Token::Match(parent->astParent(), "%oror%|&&|(|,|.|!|;|return")) return false; if (op->str() == "&" && parent->astParent()) return false; diff --git a/test/testother.cpp b/test/testother.cpp index 33fe01276e1..1c0fb8b9fdd 100644 --- a/test/testother.cpp +++ b/test/testother.cpp @@ -3270,6 +3270,12 @@ class TestOther : public TestFixture { " const int* p = s.g();\n" "}\n"); ASSERT_EQUALS("", errout.str()); + + check("struct S { int x; };\n" // #11818 + "std::istream& f(std::istream& is, S& s) {\n" + " return is >> s.x;\n" + "}\n"); + ASSERT_EQUALS("", errout.str()); } void constParameterCallback() { From b9acaab20d74f18aa3c84616031fe4473c2cf469 Mon Sep 17 00:00:00 2001 From: chrchr Date: Fri, 7 Jul 2023 13:15:04 +0200 Subject: [PATCH 4/4] Fix #11814 FP unknownMacro with designated initializer --- lib/tokenize.cpp | 2 +- test/testtokenize.cpp | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/lib/tokenize.cpp b/lib/tokenize.cpp index 21efa72c1b3..9b5c4f07850 100644 --- a/lib/tokenize.cpp +++ b/lib/tokenize.cpp @@ -8058,7 +8058,7 @@ void Tokenizer::reportUnknownMacros() const // Report unknown macros before } "{ .. if (x) MACRO }" for (const Token *tok = tokens(); tok; tok = tok->next()) { - if (Token::Match(tok, ")|; %name% }")) { + if (Token::Match(tok, ")|; %name% } !!)")) { const Token* prev = tok->linkAt(2); while (Token::simpleMatch(prev, "{")) prev = prev->previous(); diff --git a/test/testtokenize.cpp b/test/testtokenize.cpp index 3688748c349..0ff011e8637 100644 --- a/test/testtokenize.cpp +++ b/test/testtokenize.cpp @@ -6876,6 +6876,10 @@ class TestTokenizer : public TestFixture { ASSERT_THROW(tokenizeAndStringify("void foo() { if(x) SYSTEM_ERROR }"), InternalError); ASSERT_THROW(tokenizeAndStringify("void foo() { dostuff(); SYSTEM_ERROR }"), InternalError); + + ASSERT_NO_THROW(tokenizeAndStringify("void f(void* q) {\n" + " g(&(S) { .p = (int*)q });\n" + "}\n", /*expand*/ true, cppcheck::Platform::Type::Native, "test.c")); } void findGarbageCode() { // Test Tokenizer::findGarbageCode()