diff --git a/lib/checkbufferoverrun.cpp b/lib/checkbufferoverrun.cpp index 987ab2605..da88c7f37 100644 --- a/lib/checkbufferoverrun.cpp +++ b/lib/checkbufferoverrun.cpp @@ -1015,9 +1015,14 @@ void CheckBufferOverrun::checkScope_inner(const Token *tok, const ArrayInfo &arr const Token * const sizeArg = args.size() == 3 ? args[2] : nullptr; const bool knownSize = sizeArg && sizeArg->hasKnownIntValue(); const Token * const endToken = tok2->linkAt(1); + const bool smallerSrcString = (args.size() == 3 && + args[1]->hasKnownValue() && + args[1]->values().front().isTokValue() && + args[1]->values().front().tokvalue->tokType() == Token::eString && + Token::getStrLength(args[1]->values().front().tokvalue) < sizeArg->getKnownIntValue()); // check for strncpy which is not terminated - if (knownSize && tok2->str() == "strncpy") { + if (knownSize && !smallerSrcString && tok2->str() == "strncpy") { // strncpy takes entire variable length as input size const MathLib::bigint num = sizeArg->getKnownIntValue(); @@ -1040,7 +1045,7 @@ void CheckBufferOverrun::checkScope_inner(const Token *tok, const ArrayInfo &arr } // Dangerous usage of strncat.. - else if (knownSize && tok2->str() == "strncat") { + else if (knownSize && !smallerSrcString && tok2->str() == "strncat") { const MathLib::bigint n = sizeArg->getKnownIntValue(); if (n >= total_size) strncatUsageError(tok2); diff --git a/test/testbufferoverrun.cpp b/test/testbufferoverrun.cpp index 1290471e3..18fb39ac8 100644 --- a/test/testbufferoverrun.cpp +++ b/test/testbufferoverrun.cpp @@ -221,6 +221,7 @@ private: TEST_CASE(terminateStrncpy1); TEST_CASE(terminateStrncpy2); TEST_CASE(terminateStrncpy3); + TEST_CASE(terminateStrncpy4); TEST_CASE(recursive_long_time); TEST_CASE(crash1); // Ticket #1587 - crash @@ -3605,6 +3606,20 @@ private: ASSERT_EQUALS("[test.cpp:4]: (warning, inconclusive) The buffer 'str' may not be null-terminated after the call to strncpy().\n", errout.str()); } + void terminateStrncpy4() { + check("void bar() {\n" + " char buf[4];\n" + " strncpy(buf, \"ab\", 4);\n" + "}\n"); + ASSERT_EQUALS("", errout.str()); + + check("void bar() {\n" + " char buf[4];\n" + " strncpy(buf, \"abcde\", 4);\n" + "}\n"); + ASSERT_EQUALS("[test.cpp:3]: (warning, inconclusive) The buffer 'buf' is not null-terminated after the call to strncpy().\n", errout.str()); + } + void recursive_long_time() { // Just test that recursive check doesn't take long time check("char *f2 ( char *b )\n"