From 5b9fa9657d664eb602fe8714f4d6d5b843e7562d Mon Sep 17 00:00:00 2001 From: chrchr-github <78114321+chrchr-github@users.noreply.github.com> Date: Mon, 20 Jun 2022 20:02:22 +0200 Subject: [PATCH] Partial fix for #11137 FN: invalidFunctionArgStr printf argument (#4224) * Partial fix for #11137 FN: invalidFunctionArgStr printf argument * Typo * Remove , suppressions * Add suppresion, remove * Add suppressions --- cfg/posix.cfg | 1 - cfg/std.cfg | 1 - lib/checkfunctions.cpp | 9 ++++++++- test/cfg/posix.c | 2 -- test/cfg/std.c | 7 ++++--- test/testfunctions.cpp | 12 ++++++++++++ 6 files changed, 24 insertions(+), 8 deletions(-) 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() {