diff --git a/cfg/posix.cfg b/cfg/posix.cfg index d5f369496..9fa1597f4 100644 --- a/cfg/posix.cfg +++ b/cfg/posix.cfg @@ -5279,7 +5279,6 @@ The function 'mktemp' is considered to be dangerous due to race conditions and s - diff --git a/cfg/std.cfg b/cfg/std.cfg index 566f7104c..c7633313a 100644 --- a/cfg/std.cfg +++ b/cfg/std.cfg @@ -5209,7 +5209,6 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun - diff --git a/lib/checkfunctions.cpp b/lib/checkfunctions.cpp index 75538c309..1d6ce74b9 100644 --- a/lib/checkfunctions.cpp +++ b/lib/checkfunctions.cpp @@ -141,7 +141,7 @@ void CheckFunctions::invalidFunctionUsage() const Variable* const variable = argtok->variable(); // Is non-null terminated local variable of type char (e.g. char buf[] = {'x'};) ? if (variable && variable->isLocal() - && valueType && valueType->type == ValueType::Type::CHAR) { + && valueType && (valueType->type == ValueType::Type::CHAR || valueType->type == ValueType::Type::WCHAR_T)) { const Token* varTok = variable->declEndToken(); auto count = -1; // Find out explicitly set count, e.g.: char buf[3] = {...}. Variable 'count' is set to 3 then. if (varTok && Token::simpleMatch(varTok->previous(), "]")) @@ -170,6 +170,13 @@ void CheckFunctions::invalidFunctionUsage() && (count == -1 || (count > 0 && count <= charsUntilFirstZero))) { invalidFunctionArgStrError(argtok, functionToken->str(), argnr); } + } else if (count > -1 && Token::Match(varTok, "= %str%")) { + const Token* strTok = varTok->getValueTokenMinStrSize(mSettings); + if (strTok) { + const int strSize = Token::getStrArraySize(strTok); + if (strSize > count) + invalidFunctionArgStrError(argtok, functionToken->str(), argnr); + } } } } diff --git a/test/cfg/posix.c b/test/cfg/posix.c index d45cc26f2..aad6217ee 100644 --- a/test/cfg/posix.c +++ b/test/cfg/posix.c @@ -558,9 +558,7 @@ void bufferAccessOutOfBounds_bzero(void *s, size_t n) size_t bufferAccessOutOfBounds_strnlen(const char *s, size_t maxlen) { const char buf[2]={'4','2'}; - // cppcheck-suppress invalidFunctionArgStr size_t len = strnlen(buf,2); - // cppcheck-suppress invalidFunctionArgStr // cppcheck-suppress bufferAccessOutOfBounds len+=strnlen(buf,3); return len; diff --git a/test/cfg/std.c b/test/cfg/std.c index 873adef83..684c4dd7a 100644 --- a/test/cfg/std.c +++ b/test/cfg/std.c @@ -34,7 +34,7 @@ size_t invalidFunctionArgStr_wcslen(void) const wchar_t terminated0[] = L"ABCDEF49620910"; const wchar_t terminated1[3] = { L'a', L'b', L'\0' }; const wchar_t notTerminated[3] = { L'a', L'b', L'c' }; - // TODO: cppcheck-suppress invalidFunctionArgStr + // cppcheck-suppress invalidFunctionArgStr (void) wcslen(notTerminated); (void) wcslen(terminated0); return wcslen(terminated1); @@ -3908,10 +3908,11 @@ void bufferAccessOutOfBounds_strxfrm(void) { const char src[3] = "abc"; char dest[1] = "a"; + // cppcheck-suppress invalidFunctionArgStr (void)strxfrm(dest,src,1); - // cppcheck-suppress bufferAccessOutOfBounds + // cppcheck-suppress [bufferAccessOutOfBounds,invalidFunctionArgStr] (void)strxfrm(dest,src,2); - // cppcheck-suppress bufferAccessOutOfBounds + // cppcheck-suppress [bufferAccessOutOfBounds,invalidFunctionArgStr] (void)strxfrm(dest,src,3); } diff --git a/test/testfunctions.cpp b/test/testfunctions.cpp index e95c0fc8c..33d05ff82 100644 --- a/test/testfunctions.cpp +++ b/test/testfunctions.cpp @@ -711,6 +711,18 @@ private: " }\n" "}"); ASSERT_EQUALS("", errout.str()); + + check("int f() {\n" + " const char c[3] = \"abc\";\n" + " return strlen(c);\n" + "}\n"); + ASSERT_EQUALS("[test.cpp:3]: (error) Invalid strlen() argument nr 1. A nul-terminated string is required.\n", errout.str()); + + check("int f() {\n" + " const wchar_t c[3] = L\"abc\";\n" + " return wcslen(c);\n" + "}\n"); + ASSERT_EQUALS("[test.cpp:3]: (error) Invalid wcslen() argument nr 1. A nul-terminated string is required.\n", errout.str()); } void mathfunctionCall_sqrt() {