diff --git a/cfg/cppcheck-cfg.rng b/cfg/cppcheck-cfg.rng index 432c84fee..ef5a30907 100644 --- a/cfg/cppcheck-cfg.rng +++ b/cfg/cppcheck-cfg.rng @@ -273,7 +273,7 @@ - (-?[0-9]*(\.[0-9]+)?([eE][-+]?[0-9]+)?[,:])*([-]?[0-9]+(\.[0-9]+)?([eE][-+]?[0-9]+)?)? + ([-!]?[0-9]*(\.[0-9]+)?([eE][-+]?[0-9]+)?[,:])*([-!]?[0-9]+(\.[0-9]+)?([eE][-+]?[0-9]+)?)? diff --git a/cfg/std.cfg b/cfg/std.cfg index c56b3a286..dd0ce0ef5 100644 --- a/cfg/std.cfg +++ b/cfg/std.cfg @@ -4156,6 +4156,61 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun + + + + + + + false + + + + + + + !0.0 + + + + + + + + + + + false + + + + + + + !0.0 + + + + + + + + + + + false + + + + + + + !0.0 + + + + + @@ -4168,6 +4223,7 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun + !0.0 @@ -4182,6 +4238,7 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun + !0.0 @@ -4196,6 +4253,7 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun + !0.0 diff --git a/lib/library.cpp b/lib/library.cpp index 320ed6c4b..2bd2e61cc 100644 --- a/lib/library.cpp +++ b/lib/library.cpp @@ -748,7 +748,8 @@ Library::Error Library::loadFunction(const tinyxml2::XMLElement * const node, co return Error(ErrorCode::BAD_ATTRIBUTE_VALUE, (!p ? "\"\"" : argnode->GetText())); // Set validation expression ac.valid = argnode->GetText(); - } else if (argnodename == "minsize") { + } + else if (argnodename == "minsize") { const char *typeattr = argnode->Attribute("type"); if (!typeattr) return Error(ErrorCode::MISSING_ATTRIBUTE, "type"); @@ -929,6 +930,10 @@ bool Library::isFloatArgValid(const Token *ftok, int argnr, double argvalue) con return true; if ((!tok->previous() || tok->previous()->str() == ",") && Token::Match(tok,": %num%") && argvalue <= MathLib::toDoubleNumber(tok->strAt(1))) return true; + if (Token::Match(tok, "%num%") && MathLib::isFloat(tok->str()) && MathLib::isEqual(tok->str(), MathLib::toString(argvalue))) + return true; + if (Token::Match(tok, "! %num%") && MathLib::isFloat(tok->next()->str())) + return MathLib::isNotEqual(tok->next()->str(), MathLib::toString(argvalue)); } return false; } @@ -1227,7 +1232,7 @@ const Library::WarnInfo* Library::getWarnInfo(const Token* ftok) const bool Library::isCompliantValidationExpression(const char* p) { - if (!p) + if (!p || !*p) return false; bool error = false; @@ -1237,15 +1242,18 @@ bool Library::isCompliantValidationExpression(const char* p) error = *p == '.'; for (; *p; p++) { - if (std::isdigit(*p)) + if (std::isdigit(*p)) { error |= (*(p + 1) == '-'); + } else if (*p == ':') { error |= range | (*(p + 1) == '.'); range = true; has_dot = false; has_E = false; - } else if ((*p == '-') || (*p == '+')) + } + else if ((*p == '-') || (*p == '+')) { error |= (!std::isdigit(*(p + 1))); + } else if (*p == ',') { range = false; error |= *(p + 1) == '.'; @@ -1257,6 +1265,8 @@ bool Library::isCompliantValidationExpression(const char* p) } else if (*p == 'E' || *p == 'e') { error |= has_E; has_E = true; + } else if (*p == '!') { + error |= !((*(p+1) == '-') || (*(p+1) == '+') || (std::isdigit(*(p + 1)))); } else return false; } diff --git a/test/cfg/std.c b/test/cfg/std.c index b642ce477..5efd9a59f 100644 --- a/test/cfg/std.c +++ b/test/cfg/std.c @@ -30,6 +30,60 @@ #include +float invalidFunctionArg_float_remquo (float x, float y, int* quo ) +{ + // cppcheck-suppress invalidFunctionArg + (void) remquo(x,0.0f,quo); + // cppcheck-suppress invalidFunctionArg + (void) remquof(x,0.0f,quo); + return remquo(x,y,quo); +} + +double invalidFunctionArg_double_remquo (double x, double y, int* quo ) +{ + // cppcheck-suppress invalidFunctionArg + (void) remquo(x,0.0,quo); + // cppcheck-suppress invalidFunctionArg + (void) remquo(x,0.0f,quo); + // cppcheck-suppress invalidFunctionArg + (void) remquo(x,0.0L,quo); + return remquo(x,y,quo); +} + +double invalidFunctionArg_long_double_remquo (long double x, long double y, int* quo ) +{ + // cppcheck-suppress invalidFunctionArg + (void) remquo(x,0.0L,quo); + // cppcheck-suppress invalidFunctionArg + (void) remquol(x,0.0L,quo); + return remquo(x,y,quo); +} + +void invalidFunctionArg_remainderl(long double f1, long double f2) +{ + // cppcheck-suppress invalidFunctionArg + (void)remainderl(f1,0.0); + // cppcheck-suppress invalidFunctionArg + (void)remainderl(f1,0.0L); + (void)remainderl(f1,f2); +} + +void invalidFunctionArg_remainder(double f1, double f2) +{ + // cppcheck-suppress invalidFunctionArg + (void)remainder(f1,0.0); + (void)remainder(f1,f2); +} + +void invalidFunctionArg_remainderf(float f1, float f2) +{ + // cppcheck-suppress invalidFunctionArg + (void)remainderf(f1,0.0); + // cppcheck-suppress invalidFunctionArg + (void)remainderf(f1,0.0f); + (void)remainderf(f1,f2); +} + int qsort_cmpfunc (const void * a, const void * b) { return (*(int*)a - *(int*)b); } diff --git a/test/cfg/std.cpp b/test/cfg/std.cpp index 431f6b21a..4803f90e7 100644 --- a/test/cfg/std.cpp +++ b/test/cfg/std.cpp @@ -36,6 +36,60 @@ #include #include +float invalidFunctionArg_remquo (float x, float y, int* quo ) +{ + // cppcheck-suppress invalidFunctionArg + (void) std::remquo(x,0.0f,quo); + // cppcheck-suppress invalidFunctionArg + (void) std::remquof(x,0.0f,quo); + return std::remquo(x,y,quo); +} + +double invalidFunctionArg_remquo (double x, double y, int* quo ) +{ + // cppcheck-suppress invalidFunctionArg + (void) std::remquo(x,0.0,quo); + // cppcheck-suppress invalidFunctionArg + (void) std::remquo(x,0.0f,quo); + // cppcheck-suppress invalidFunctionArg + (void) std::remquo(x,0.0L,quo); + return std::remquo(x,y,quo); +} + +double invalidFunctionArg_remquo (long double x, long double y, int* quo ) +{ + // cppcheck-suppress invalidFunctionArg + (void) std::remquo(x,0.0L,quo); + // cppcheck-suppress invalidFunctionArg + (void) std::remquol(x,0.0L,quo); + return std::remquo(x,y,quo); +} + +void invalidFunctionArg_remainderl(long double f1, long double f2) +{ + // cppcheck-suppress invalidFunctionArg + (void)std::remainderl(f1,0.0); + // cppcheck-suppress invalidFunctionArg + (void)std::remainderl(f1,0.0L); + (void)std::remainderl(f1,f2); +} + +void invalidFunctionArg_remainder(double f1, double f2) +{ + // cppcheck-suppress invalidFunctionArg + (void)std::remainder(f1,0.0); + (void)std::remainder(f1,f2); +} + +void invalidFunctionArg_remainderf(float f1, float f2) +{ + // cppcheck-suppress invalidFunctionArg + (void)std::remainderf(f1,0.0); + // cppcheck-suppress invalidFunctionArg + (void)std::remainderf(f1,0.0f); + (void)std::remainderf(f1,f2); +} + void uninitvar_std_fstream_open(std::fstream &fs, const std::string &strFileName, const char* filename, std::ios_base::openmode mode) { std::string s; diff --git a/test/testlibrary.cpp b/test/testlibrary.cpp index 2c6d2b0cf..c1975fff6 100644 --- a/test/testlibrary.cpp +++ b/test/testlibrary.cpp @@ -89,10 +89,13 @@ private: ASSERT_EQUALS(true, Library::isCompliantValidationExpression("1.175494e-38:")); ASSERT_EQUALS(true, Library::isCompliantValidationExpression(":1.175494e-38")); ASSERT_EQUALS(true, Library::isCompliantValidationExpression(":42.0")); + ASSERT_EQUALS(true, Library::isCompliantValidationExpression("!42.0")); // Robustness tests ASSERT_EQUALS(false, Library::isCompliantValidationExpression(nullptr)); ASSERT_EQUALS(false, Library::isCompliantValidationExpression("x")); + ASSERT_EQUALS(false, Library::isCompliantValidationExpression("!")); + ASSERT_EQUALS(false, Library::isCompliantValidationExpression("")); } void empty() const { @@ -336,6 +339,7 @@ private: " 0.0:\n" " :2.0\n" " 0.0\n" + " !0.0\n" " \n" ""; @@ -343,7 +347,7 @@ private: ASSERT_EQUALS(true, Library::ErrorCode::OK == (readLibrary(library, xmldata)).errorcode); TokenList tokenList(nullptr); - std::istringstream istr("foo(a,b,c,d,e,f,g,h,i,j);"); + std::istringstream istr("foo(a,b,c,d,e,f,g,h,i,j,k);"); tokenList.createTokens(istr); tokenList.front()->next()->astOperand1(tokenList.front()); @@ -460,8 +464,13 @@ private: ASSERT_EQUALS(false, library.isFloatArgValid(tokenList.front(), 9, 200.0)); // 0.0 - ASSERT_EQUALS(false, library.isIntArgValid(tokenList.front(), 10, 0)); - ASSERT_EQUALS(false, library.isFloatArgValid(tokenList.front(), 10, 0.0)); + ASSERT_EQUALS(true, library.isIntArgValid(tokenList.front(), 10, 0)); + ASSERT_EQUALS(true, library.isFloatArgValid(tokenList.front(), 10, 0.0)); + + // ! 0.0 + ASSERT_EQUALS(true, library.isFloatArgValid(tokenList.front(), 11, -0.42)); + ASSERT_EQUALS(false, library.isFloatArgValid(tokenList.front(), 11, 0.0)); + ASSERT_EQUALS(true, library.isFloatArgValid(tokenList.front(), 11, 0.42)); } void function_arg_minsize() const {