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 {