Fixed false positives from terminateStrncpy

This commit is contained in:
Daniel Marjamäki 2019-03-06 18:50:50 +01:00
parent 1fe1fc7008
commit c32d015337
2 changed files with 22 additions and 2 deletions

View File

@ -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 Token * const sizeArg = args.size() == 3 ? args[2] : nullptr;
const bool knownSize = sizeArg && sizeArg->hasKnownIntValue(); const bool knownSize = sizeArg && sizeArg->hasKnownIntValue();
const Token * const endToken = tok2->linkAt(1); 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 // 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 // strncpy takes entire variable length as input size
const MathLib::bigint num = sizeArg->getKnownIntValue(); const MathLib::bigint num = sizeArg->getKnownIntValue();
@ -1040,7 +1045,7 @@ void CheckBufferOverrun::checkScope_inner(const Token *tok, const ArrayInfo &arr
} }
// Dangerous usage of strncat.. // Dangerous usage of strncat..
else if (knownSize && tok2->str() == "strncat") { else if (knownSize && !smallerSrcString && tok2->str() == "strncat") {
const MathLib::bigint n = sizeArg->getKnownIntValue(); const MathLib::bigint n = sizeArg->getKnownIntValue();
if (n >= total_size) if (n >= total_size)
strncatUsageError(tok2); strncatUsageError(tok2);

View File

@ -221,6 +221,7 @@ private:
TEST_CASE(terminateStrncpy1); TEST_CASE(terminateStrncpy1);
TEST_CASE(terminateStrncpy2); TEST_CASE(terminateStrncpy2);
TEST_CASE(terminateStrncpy3); TEST_CASE(terminateStrncpy3);
TEST_CASE(terminateStrncpy4);
TEST_CASE(recursive_long_time); TEST_CASE(recursive_long_time);
TEST_CASE(crash1); // Ticket #1587 - crash 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()); 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() { void recursive_long_time() {
// Just test that recursive check doesn't take long time // Just test that recursive check doesn't take long time
check("char *f2 ( char *b )\n" check("char *f2 ( char *b )\n"