From 2334192bff774e4070111283dc18345ae681835e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Marjam=C3=A4ki?= Date: Tue, 12 Oct 2010 21:52:02 +0200 Subject: [PATCH 01/10] Fixed #2087 (False positive: Array 'str[1]' index 1 out of bounds) --- lib/tokenize.cpp | 6 ++++++ test/testsimplifytokens.cpp | 6 ++++++ 2 files changed, 12 insertions(+) diff --git a/lib/tokenize.cpp b/lib/tokenize.cpp index da3bfcddc..80ece70fb 100644 --- a/lib/tokenize.cpp +++ b/lib/tokenize.cpp @@ -2095,6 +2095,12 @@ void Tokenizer::arraySize() { for (Token *tok = _tokens; tok; tok = tok->next()) { + if (Token::Match(tok, "%var% [ ] = { %str% }")) + { + tok->tokAt(4)->deleteThis(); + tok->tokAt(5)->deleteThis(); + } + if (Token::Match(tok, "%var% [ ] = {")) { unsigned int sz = 1; diff --git a/test/testsimplifytokens.cpp b/test/testsimplifytokens.cpp index 1fc813a69..0adc5e81f 100644 --- a/test/testsimplifytokens.cpp +++ b/test/testsimplifytokens.cpp @@ -934,6 +934,12 @@ private: ASSERT_EQUALS("; const char str [ 1 ] = { '1' } ; 1 ;", sizeof_(code)); } + { + // Ticket #2087 + const char code[] = "; const char str[] = {\"abc\"}; sizeof(str);"; + ASSERT_EQUALS("; const char str [ 4 ] = \"abc\" ; 4 ;", sizeof_(code)); + } + // ticket #716 - sizeof string { std::ostringstream expected; From a58094e827197bcac7cba5a376d6289e79bf3fb8 Mon Sep 17 00:00:00 2001 From: Robert Reif Date: Wed, 13 Oct 2010 07:26:41 +0200 Subject: [PATCH 02/10] Fixed #2089 (False negative: Function can be const (calling const function)) --- lib/checkclass.cpp | 44 +++++++++++++++++++++++++++++++++++++++++--- lib/checkclass.h | 1 + test/testclass.cpp | 2 +- 3 files changed, 43 insertions(+), 4 deletions(-) diff --git a/lib/checkclass.cpp b/lib/checkclass.cpp index 44b4afc3f..892a78dfd 100644 --- a/lib/checkclass.cpp +++ b/lib/checkclass.cpp @@ -2139,6 +2139,37 @@ bool CheckClass::isMemberVar(const SpaceInfo *info, const Token *tok) return false; } +bool CheckClass::isConstMemberFunc(const SpaceInfo *info, const Token *tok) +{ + std::list::const_iterator func; + + for (func = info->functionList.begin(); func != info->functionList.end(); ++func) + { + if (func->tokenDef->str() == tok->str() && func->isConst) + return true; + } + + // not found in this class + if (!info->derivedFrom.empty()) + { + // check each base class + for (unsigned int i = 0; i < info->derivedFrom.size(); ++i) + { + // find the base class + const SpaceInfo *spaceInfo = info->derivedFrom[i].spaceInfo; + + // find the function in the base class + if (spaceInfo) + { + if (isConstMemberFunc(spaceInfo, tok)) + return true; + } + } + } + + return false; +} + bool CheckClass::checkConstFunc(const SpaceInfo *info, const Token *tok) { // if the function doesn't have any assignment nor function call, @@ -2200,9 +2231,16 @@ bool CheckClass::checkConstFunc(const SpaceInfo *info, const Token *tok) } // function call.. - else if ((Token::Match(tok1, "%var% (") && - !(Token::Match(tok1, "return|c_str|if|string") || tok1->isStandardType())) || - Token::Match(tok1, "%var% < %any% > (")) + else if (Token::Match(tok1, "%var% (") && + !(Token::Match(tok1, "return|c_str|if|string") || tok1->isStandardType())) + { + if (!isConstMemberFunc(info, tok1)) + { + isconst = false; + break; + } + } + else if (Token::Match(tok1, "%var% < %any% > (")) { isconst = false; break; diff --git a/lib/checkclass.h b/lib/checkclass.h index eb86322a9..279b2cacf 100644 --- a/lib/checkclass.h +++ b/lib/checkclass.h @@ -305,6 +305,7 @@ private: bool argsMatch(const Token *first, const Token *second, const std::string &path, unsigned int depth) const; bool isMemberVar(const SpaceInfo *info, const Token *tok); + bool isConstMemberFunc(const SpaceInfo *info, const Token *tok); bool checkConstFunc(const SpaceInfo *info, const Token *tok); const Token *initBaseInfo(SpaceInfo *info, const Token *tok); diff --git a/test/testclass.cpp b/test/testclass.cpp index 34e9dbae2..a40d130d9 100644 --- a/test/testclass.cpp +++ b/test/testclass.cpp @@ -4130,7 +4130,7 @@ private: " void f() const { };\n" " void a() { f(); };\n" "};\n"); - TODO_ASSERT_EQUALS("[test.cpp:3]: (style) The function 'Fred::a' can be const\n", errout.str()); + ASSERT_EQUALS("[test.cpp:3]: (style) The function 'Fred::a' can be const\n", errout.str()); // ticket #1593 checkConst("#include \n" From fbd3d92aa95ab1238548c8a7e4a45b112be388ab Mon Sep 17 00:00:00 2001 From: Pete Johns Date: Wed, 13 Oct 2010 20:31:41 +1100 Subject: [PATCH 03/10] Fixed #2084 (False positive: object destroyed immediately (struct and function with same name)) Tightened up class definition matching so as not to match C-style struct tags. --- lib/checkother.cpp | 7 ++++--- test/testother.cpp | 16 ++++++++++++++++ 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/lib/checkother.cpp b/lib/checkother.cpp index 346270f33..3aa5e6f6d 100644 --- a/lib/checkother.cpp +++ b/lib/checkother.cpp @@ -3884,8 +3884,8 @@ bool CheckOther::isIdentifierObjectType(const Token * const tok) return found->second; } - const std::string classDef = std::string("class|struct ") + identifier; - const bool result = Token::findmatch(_tokenizer->tokens(), classDef.c_str()); + const std::string classDefnOrDecl = std::string("class|struct ") + identifier + " [{:;]"; + const bool result = Token::findmatch(_tokenizer->tokens(), classDefnOrDecl.c_str()); isClassResults.insert(std::make_pair(identifier, result)); return result; } @@ -3893,6 +3893,7 @@ bool CheckOther::isIdentifierObjectType(const Token * const tok) void CheckOther::checkMisusedScopedObject() { + const char localClassDefinition[] = "class|struct %var% [{:]"; bool withinFunction = false; unsigned int depth = 0; std::string className = ""; @@ -3917,7 +3918,7 @@ void CheckOther::checkMisusedScopedObject() className.clear(); } } - else if (Token::Match(tok, "class|struct")) + else if (Token::Match(tok, localClassDefinition)) { className = tok->strAt(1); isClassResults.insert(std::make_pair(className, false)); diff --git a/test/testother.cpp b/test/testother.cpp index 931ddc247..1e4b12bd0 100644 --- a/test/testother.cpp +++ b/test/testother.cpp @@ -115,6 +115,7 @@ private: TEST_CASE(testMisusedScopeObjectDoesNotPickLocalClassConstructors); TEST_CASE(testMisusedScopeObjectDoesNotPickUsedObject); TEST_CASE(trac2071); + TEST_CASE(trac2084); TEST_CASE(assignmentInAssert); } @@ -3160,6 +3161,21 @@ private: ASSERT_EQUALS("", errout.str()); } + void trac2084() + { + check("#include \n" + "\n" + "void f()\n" + "{\n" + " struct sigaction sa;\n" + "\n" + " { sigaction(SIGHUP, &sa, 0); };\n" + " { sigaction(SIGINT, &sa, 0); };\n" + "}\n" + ); + ASSERT_EQUALS("", errout.str()); + } + void trac2071() { check("void f() {\n" From 52e16454faf8c90293e71f1782bd5a10215ca799 Mon Sep 17 00:00:00 2001 From: Pete Johns Date: Wed, 13 Oct 2010 20:48:37 +1100 Subject: [PATCH 04/10] Removed redundant code. localClassDefinition is no longer required due to improved isIdentifierObjectType() in commit fbd3d92. --- lib/checkother.cpp | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/lib/checkother.cpp b/lib/checkother.cpp index 3aa5e6f6d..3dae17ab0 100644 --- a/lib/checkother.cpp +++ b/lib/checkother.cpp @@ -3893,10 +3893,8 @@ bool CheckOther::isIdentifierObjectType(const Token * const tok) void CheckOther::checkMisusedScopedObject() { - const char localClassDefinition[] = "class|struct %var% [{:]"; bool withinFunction = false; unsigned int depth = 0; - std::string className = ""; for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next()) { @@ -3911,17 +3909,6 @@ void CheckOther::checkMisusedScopedObject() { --depth; withinFunction &= depth > 0; - - if (tok->strAt(1) == ";" && !className.empty()) - { - isClassResults[className] = true; - className.clear(); - } - } - else if (Token::Match(tok, localClassDefinition)) - { - className = tok->strAt(1); - isClassResults.insert(std::make_pair(className, false)); } if (withinFunction From afe52fa9f2d0594c794e9b6e988d11687a399ad3 Mon Sep 17 00:00:00 2001 From: Pete Johns Date: Wed, 13 Oct 2010 21:19:18 +1100 Subject: [PATCH 05/10] Fixed MSVC++ compiler warning (pointers are not bools) --- lib/checkother.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/checkother.cpp b/lib/checkother.cpp index 3dae17ab0..25c5bcd58 100644 --- a/lib/checkother.cpp +++ b/lib/checkother.cpp @@ -3885,7 +3885,7 @@ bool CheckOther::isIdentifierObjectType(const Token * const tok) } const std::string classDefnOrDecl = std::string("class|struct ") + identifier + " [{:;]"; - const bool result = Token::findmatch(_tokenizer->tokens(), classDefnOrDecl.c_str()); + const bool result = Token::findmatch(_tokenizer->tokens(), classDefnOrDecl.c_str()) != NULL; isClassResults.insert(std::make_pair(identifier, result)); return result; } From 229604b3e31db0e99f8675da9d19fd77dd130e24 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Marjam=C3=A4ki?= Date: Wed, 13 Oct 2010 18:06:50 +0200 Subject: [PATCH 06/10] Fixed #2093 (False positive: buffer access out of bounds (unknown type)) --- lib/checkbufferoverrun.cpp | 2 +- test/testbufferoverrun.cpp | 7 +++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/lib/checkbufferoverrun.cpp b/lib/checkbufferoverrun.cpp index b565d3682..fa2ef130e 100644 --- a/lib/checkbufferoverrun.cpp +++ b/lib/checkbufferoverrun.cpp @@ -1012,7 +1012,7 @@ void CheckBufferOverrun::checkScope(const Token *tok, const ArrayInfo &arrayInfo if (Token::Match(tok, "strcpy|strcat ( %varid% , %str% )", arrayInfo.varid)) { const unsigned long len = Token::getStrLength(tok->tokAt(4)); - if (len >= total_size) + if (total_size > 0 && len >= total_size) { bufferOverrun(tok, arrayInfo.varname); continue; diff --git a/test/testbufferoverrun.cpp b/test/testbufferoverrun.cpp index 683744e99..d4cbedba1 100644 --- a/test/testbufferoverrun.cpp +++ b/test/testbufferoverrun.cpp @@ -1688,11 +1688,18 @@ private: void buffer_overrun_16() { + // unknown types check("void f() {\n" " struct Foo foo[5];\n" " memset(foo, 0, sizeof(foo));\n" "}\n"); ASSERT_EQUALS("", errout.str()); + + check("void f() {\n" // ticket #2093 + " gchar x[3];\n" + " strcpy(x, \"12\");\n" + "}\n"); + ASSERT_EQUALS("", errout.str()); } void sprintf1() From 267d1f273e0eeaf45db1049ee5b28b63008de727 Mon Sep 17 00:00:00 2001 From: Robert Reif Date: Wed, 13 Oct 2010 20:02:37 +0200 Subject: [PATCH 07/10] Fixed #2082 (Tokenizer::simplifyTypedef: wrong handling of array) --- lib/tokenize.cpp | 35 ++++++++++++++++++++--------------- test/testsimplifytokens.cpp | 18 ++++++++++++++++++ 2 files changed, 38 insertions(+), 15 deletions(-) diff --git a/lib/tokenize.cpp b/lib/tokenize.cpp index 80ece70fb..4f7d7c0dc 100644 --- a/lib/tokenize.cpp +++ b/lib/tokenize.cpp @@ -1594,28 +1594,33 @@ void Tokenizer::simplifyTypedef() if (arrayStart && arrayEnd) { - tok2 = tok2->next(); - Token * nextArrTok; - std::stack arrLinks; - for (nextArrTok = arrayStart; nextArrTok != arrayEnd->next(); nextArrTok = nextArrTok->next()) + do { - tok2->insertToken(nextArrTok->strAt(0)); tok2 = tok2->next(); - - // Check for links and fix them up - if (tok2->str() == "(" || tok2->str() == "[") - arrLinks.push(tok2); - if (tok2->str() == ")" || tok2->str() == "]") + Token * nextArrTok; + std::stack arrLinks; + for (nextArrTok = arrayStart; nextArrTok != arrayEnd->next(); nextArrTok = nextArrTok->next()) { - Token * link = arrLinks.top(); + tok2->insertToken(nextArrTok->strAt(0)); + tok2 = tok2->next(); - tok2->link(link); - link->link(tok2); + // Check for links and fix them up + if (tok2->str() == "(" || tok2->str() == "[") + arrLinks.push(tok2); + if (tok2->str() == ")" || tok2->str() == "]") + { + Token * link = arrLinks.top(); - arrLinks.pop(); + tok2->link(link); + link->link(tok2); + + arrLinks.pop(); + } } + + tok2 = tok2->next(); } - tok2 = tok2->next(); + while (Token::Match(tok2, ", %var% ;|'")); } simplifyType = false; diff --git a/test/testsimplifytokens.cpp b/test/testsimplifytokens.cpp index 0adc5e81f..493dfda94 100644 --- a/test/testsimplifytokens.cpp +++ b/test/testsimplifytokens.cpp @@ -217,6 +217,7 @@ private: TEST_CASE(simplifyTypedef59); // ticket #2011 TEST_CASE(simplifyTypedef60); // ticket #2035 TEST_CASE(simplifyTypedef61); // ticket #2074 and 2075 + TEST_CASE(simplifyTypedef62); // ticket #2082 TEST_CASE(simplifyTypedefFunction1); TEST_CASE(simplifyTypedefFunction2); // ticket #1685 @@ -4475,6 +4476,23 @@ private: ASSERT_EQUALS("", errout.str()); } + void simplifyTypedef62() // ticket #2082 + { + const char code[] = "typedef char TString[256];\n" + "void f()\n" + "{\n" + " TString a, b;\n" + "}"; + + // The expected tokens.. + const std::string expected("; void f ( ) { char a [ 256 ] ; char b [ 256 ] ; }"); + ASSERT_EQUALS(expected, sizeof_(code, false)); + + // Check for output.. + checkSimplifyTypedef(code); + ASSERT_EQUALS("", errout.str()); + } + void simplifyTypedefFunction1() { { From b6c995ea478c31f116597a42fff0ef9058a9fc28 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Marjam=C3=A4ki?= Date: Wed, 13 Oct 2010 20:57:59 +0200 Subject: [PATCH 08/10] Fixed #2096 (False positive: buffer overrun (extern array)) --- lib/checkbufferoverrun.cpp | 4 +++- test/testbufferoverrun.cpp | 7 +++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/lib/checkbufferoverrun.cpp b/lib/checkbufferoverrun.cpp index fa2ef130e..ecf36dfa9 100644 --- a/lib/checkbufferoverrun.cpp +++ b/lib/checkbufferoverrun.cpp @@ -1794,7 +1794,9 @@ bool CheckBufferOverrun::ArrayInfo::declare(const Token *tok, const Tokenizer &t if (!tok->isName()) return false; - while (tok && (tok->str() == "static" || tok->str() == "const")) + while (tok && (tok->str() == "static" || + tok->str() == "const" || + tok->str() == "extern")) tok = tok->next(); int ivar = 0; diff --git a/test/testbufferoverrun.cpp b/test/testbufferoverrun.cpp index d4cbedba1..7982d8bad 100644 --- a/test/testbufferoverrun.cpp +++ b/test/testbufferoverrun.cpp @@ -1700,6 +1700,13 @@ private: " strcpy(x, \"12\");\n" "}\n"); ASSERT_EQUALS("", errout.str()); + + check("extern char a[10];\n" + "void f() {\n" + " char b[25] = {0};\n" + " std::memcpy(b, a, sizeof(a));\n" + "}\n"); + ASSERT_EQUALS("", errout.str()); } void sprintf1() From dd16af3d292918f2b8dcc671133fb3945b31c7c0 Mon Sep 17 00:00:00 2001 From: Kimmo Varis Date: Wed, 13 Oct 2010 22:13:50 +0300 Subject: [PATCH 09/10] Update WiX installer documentation. --- win_installer/readme.txt | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/win_installer/readme.txt b/win_installer/readme.txt index f65ff616c..ba0011188 100644 --- a/win_installer/readme.txt +++ b/win_installer/readme.txt @@ -25,11 +25,14 @@ Building installer Before building the installer make sure all the components are build: - CLI executable (cppcheck.exe) - - GUI executable (gui.exe) - - Manual (manual.pdf) + - GUI executable (cppcheck-gui.exe) + - GUI translations (*.qm) + - Manual (onlinehelp.qhc) And that runtime files are available: - - Qt runtimes (qtcore4.dll, qtgui4.dll and qtxml4.dll) + - Qt runtimes: + QtCLucene4.dll, QtCore4.dll, QtGui4.dll, QtHelp4.dll, QtNetwork4.dll, + QtSql4.dll and QtXml4.dll - MS CRT merge module (Microsoft_VC90_CRT_x86.msm) Build installer by giving this command line in VS command prompt (or run From e199e31de15d398cc9d79505d72d09dcaf67f246 Mon Sep 17 00:00:00 2001 From: Kimmo Varis Date: Wed, 13 Oct 2010 22:15:18 +0300 Subject: [PATCH 10/10] WiX Installer: Remove old gui.exe. --- win_installer/cppcheck.wxs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/win_installer/cppcheck.wxs b/win_installer/cppcheck.wxs index 7c0017d52..fac1a3ed3 100755 --- a/win_installer/cppcheck.wxs +++ b/win_installer/cppcheck.wxs @@ -49,11 +49,13 @@ - + +