diff --git a/src/checkother.cpp b/src/checkother.cpp index 79e3f9b5e..af193a588 100644 --- a/src/checkother.cpp +++ b/src/checkother.cpp @@ -958,3 +958,28 @@ void CheckOther::functionVariableUsage() } } } +//--------------------------------------------------------------------------- + + + + + + +//--------------------------------------------------------------------------- +// str plus char +//--------------------------------------------------------------------------- + +void CheckOther::strPlusChar() +{ + for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next() ) + { + if ( Token::Match(tok, "%str% + %any%") ) + { + const char *s = tok->strAt(2); + + // char constant.. + if ( *s == '\'' ) + _errorLogger->reportErr(ErrorMessage::strPlusChar(_tokenizer, tok)); + } + } +} diff --git a/src/checkother.h b/src/checkother.h index d1d63aae2..170995546 100644 --- a/src/checkother.h +++ b/src/checkother.h @@ -71,6 +71,9 @@ public: /** Unused function variables */ void functionVariableUsage(); + /** str plus char */ + void strPlusChar(); + #ifndef UNIT_TESTING private: #endif diff --git a/src/cppcheck.cpp b/src/cppcheck.cpp index 5b702ae3c..d46eb1153 100644 --- a/src/cppcheck.cpp +++ b/src/cppcheck.cpp @@ -336,6 +336,10 @@ void CppCheck::checkFile(const std::string &code, const char FileName[]) // mean that an ';' has been added by accident if (ErrorMessage::constStatement(_settings)) checkOther.CheckIncompleteStatement(); + + // Unusual pointer arithmetic + if (ErrorMessage::strPlusChar(_settings)) + checkOther.strPlusChar(); } //--------------------------------------------------------------------------- diff --git a/src/errormessage.h b/src/errormessage.h index 50237bcb2..4104615fc 100644 --- a/src/errormessage.h +++ b/src/errormessage.h @@ -327,5 +327,14 @@ public: return s._checkCodingStyle; } + static std::string strPlusChar(const Tokenizer *tokenizer, const Token *Location) + { + return msg1(tokenizer, Location) + "Unusual pointer arithmetic"; + } + static bool strPlusChar(const Settings &s) + { + return true; + } + }; #endif diff --git a/test/testother.cpp b/test/testother.cpp index 8a1e91f76..049413078 100644 --- a/test/testother.cpp +++ b/test/testother.cpp @@ -37,10 +37,12 @@ private: TEST_CASE(delete1); TEST_CASE(delete2); - TEST_CASE(sprintf1); // Dangerous usage of sprintf + TEST_CASE(sprintf1); // Dangerous usage of sprintf TEST_CASE(sprintf2); TEST_CASE(sprintf3); - TEST_CASE(sprintf4); // struct member + TEST_CASE(sprintf4); // struct member + + TEST_CASE(strPlusChar1); // "/usr" + '/' } void check(const char code[]) @@ -157,6 +159,36 @@ private: ASSERT_EQUALS(std::string(""), errout.str()); } + + + + + void strPlusChar(const char code[]) + { + // Tokenize.. + Tokenizer tokenizer; + std::istringstream istr(code); + tokenizer.tokenize(istr, "test.cpp"); + tokenizer.setVarId(); + + // Clear the error buffer.. + errout.str(""); + + // Check for redundant code.. + CheckOther checkOther(&tokenizer, Settings(), this); + checkOther.strPlusChar(); + } + + void strPlusChar1() + { + // Strange looking pointer arithmetic.. + strPlusChar("void foo()\n" + "{\n" + " const char *p = \"/usr\" + '/';\n" + "}\n"); + ASSERT_EQUALS(std::string("[test.cpp:3]: Unusual pointer arithmetic\n"), errout.str()); + } + }; REGISTER_TEST(TestOther) diff --git a/tools/errmsg.cpp b/tools/errmsg.cpp index 0e052ed5e..f8b70a75f 100644 --- a/tools/errmsg.cpp +++ b/tools/errmsg.cpp @@ -94,6 +94,7 @@ int main() err.push_back(Message("variableScope", Message::never, "The scope of the variable %1 can be limited", "varname")); err.push_back(Message("ifAssignment", Message::style, "Assignment in if-condition")); err.push_back(Message("conditionAlwaysTrueFalse", Message::style, "Condition is always %1", "truefalse")); + err.push_back(Message("strPlusChar", Message::std, "Unusual pointer arithmetic")); // Generate code.. std::cout << "Generate code.." << std::endl;