* Fix #9944 FP: terminateStrncpy doesn't account for size check * Fix container size check * Undo * Format * Rebuild * Rebuild
This commit is contained in:
parent
a71a647c39
commit
89a9e5ecc6
|
@ -739,9 +739,18 @@ void CheckBufferOverrun::stringNotZeroTerminated()
|
||||||
const ValueFlow::Value &bufferSize = getBufferSize(args[0]);
|
const ValueFlow::Value &bufferSize = getBufferSize(args[0]);
|
||||||
if (bufferSize.intvalue < 0 || sizeToken->getKnownIntValue() < bufferSize.intvalue)
|
if (bufferSize.intvalue < 0 || sizeToken->getKnownIntValue() < bufferSize.intvalue)
|
||||||
continue;
|
continue;
|
||||||
const Token *srcValue = args[1]->getValueTokenMaxStrLength();
|
if (Token::simpleMatch(args[1], "(") && Token::simpleMatch(args[1]->astOperand1(), ". c_str") && args[1]->astOperand1()->astOperand1()) {
|
||||||
if (srcValue && Token::getStrLength(srcValue) < sizeToken->getKnownIntValue())
|
const std::list<ValueFlow::Value>& contValues = args[1]->astOperand1()->astOperand1()->values();
|
||||||
continue;
|
auto it = std::find_if(contValues.begin(), contValues.end(), [](const ValueFlow::Value& value) {
|
||||||
|
return value.isContainerSizeValue() && !value.isImpossible();
|
||||||
|
});
|
||||||
|
if (it != contValues.end() && it->intvalue < sizeToken->getKnownIntValue())
|
||||||
|
continue;
|
||||||
|
} else {
|
||||||
|
const Token* srcValue = args[1]->getValueTokenMaxStrLength();
|
||||||
|
if (srcValue && Token::getStrLength(srcValue) < sizeToken->getKnownIntValue())
|
||||||
|
continue;
|
||||||
|
}
|
||||||
// Is the buffer zero terminated after the call?
|
// Is the buffer zero terminated after the call?
|
||||||
bool isZeroTerminated = false;
|
bool isZeroTerminated = false;
|
||||||
for (const Token *tok2 = tok->next()->link(); tok2 != scope->bodyEnd; tok2 = tok2->next()) {
|
for (const Token *tok2 = tok->next()->link(); tok2 != scope->bodyEnd; tok2 = tok2->next()) {
|
||||||
|
|
|
@ -289,6 +289,7 @@ private:
|
||||||
TEST_CASE(terminateStrncpy2);
|
TEST_CASE(terminateStrncpy2);
|
||||||
TEST_CASE(terminateStrncpy3);
|
TEST_CASE(terminateStrncpy3);
|
||||||
TEST_CASE(terminateStrncpy4);
|
TEST_CASE(terminateStrncpy4);
|
||||||
|
TEST_CASE(terminateStrncpy5); // #9944
|
||||||
TEST_CASE(recursive_long_time);
|
TEST_CASE(recursive_long_time);
|
||||||
|
|
||||||
TEST_CASE(crash1); // Ticket #1587 - crash
|
TEST_CASE(crash1); // Ticket #1587 - crash
|
||||||
|
@ -4342,6 +4343,23 @@ private:
|
||||||
"}");
|
"}");
|
||||||
ASSERT_EQUALS("[test.cpp:3]: (warning, inconclusive) The buffer 'buf' may not be null-terminated after the call to strncpy().\n", errout.str());
|
ASSERT_EQUALS("[test.cpp:3]: (warning, inconclusive) The buffer 'buf' may not be null-terminated after the call to strncpy().\n", errout.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void terminateStrncpy5() { // #9944
|
||||||
|
check("void f(const std::string& buf) {\n"
|
||||||
|
" char v[255];\n"
|
||||||
|
" if (buf.size() >= sizeof(v))\n"
|
||||||
|
" return;\n"
|
||||||
|
" strncpy(v, buf.c_str(), sizeof(v));\n"
|
||||||
|
"}\n");
|
||||||
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
|
||||||
|
check("void f(const std::string& buf) {\n"
|
||||||
|
" char v[255];\n"
|
||||||
|
" if (buf.size() >= sizeof(v))\n"
|
||||||
|
" strncpy(v, buf.c_str(), sizeof(v));\n"
|
||||||
|
"}\n");
|
||||||
|
ASSERT_EQUALS("[test.cpp:4]: (warning, inconclusive) The buffer 'v' may not be null-terminated after the call to strncpy().\n", errout.str());
|
||||||
|
}
|
||||||
// extracttests.enable
|
// extracttests.enable
|
||||||
|
|
||||||
void recursive_long_time() {
|
void recursive_long_time() {
|
||||||
|
|
Loading…
Reference in New Issue