Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 21 additions & 7 deletions lib/checkbufferoverrun.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,10 @@ static const CWE CWE_BUFFER_OVERRUN(788U); // Access of Memory Location After
static const ValueFlow::Value *getBufferSizeValue(const Token *tok)
{
const std::list<ValueFlow::Value> &tokenValues = tok->values();
const auto it = std::find_if(tokenValues.cbegin(), tokenValues.cend(), std::mem_fn(&ValueFlow::Value::isBufferSizeValue));
auto it = std::find_if(tokenValues.cbegin(), tokenValues.cend(), std::mem_fn(&ValueFlow::Value::isBufferSizeValue));
if (it != tokenValues.cend())
return &*it;
it = std::find_if(tokenValues.cbegin(), tokenValues.cend(), std::mem_fn(&ValueFlow::Value::isContainerSizeValue));
return it == tokenValues.cend() ? nullptr : &*it;
}

Expand Down Expand Up @@ -552,7 +555,7 @@ void CheckBufferOverrunImpl::pointerArithmeticError(const Token *tok, const Toke

//---------------------------------------------------------------------------

ValueFlow::Value CheckBufferOverrunImpl::getBufferSize(const Token *bufTok) const
ValueFlow::Value CheckBufferOverrunImpl::getBufferSize(const Token *bufTok, const Settings& settings) const
{
if (!bufTok->valueType())
return ValueFlow::Value(-1);
Expand All @@ -569,9 +572,20 @@ ValueFlow::Value CheckBufferOverrunImpl::getBufferSize(const Token *bufTok) cons
const Variable *var = bufTok->variable();

if (!var || var->dimensions().empty()) {
const ValueFlow::Value *value = getBufferSizeValue(bufTok);
if (value)
return *value;
if (const ValueFlow::Value *value = getBufferSizeValue(bufTok)) {
if (value->isBufferSizeValue())
return *value;
if (value->isContainerSizeValue() && bufTok->valueType() && bufTok->valueType()->container) {
const ValueType vtElement = ValueType::parseDecl(bufTok->valueType()->containerTypeToken, settings);
const size_t elementSize = vtElement.getSizeOf(settings, ValueType::Accuracy::ExactOrZero, ValueType::SizeOf::Pointer);
if (elementSize > 0) {
ValueFlow::Value bufSizeVal;
bufSizeVal.valueType = ValueFlow::Value::ValueType::BUFFER_SIZE;
bufSizeVal.intvalue = value->intvalue * elementSize;
return bufSizeVal;
}
}
}
}

if (!var || var->isPointer() || (astIsContainer(bufTok) && var->getTypeName() != "std::array"))
Expand Down Expand Up @@ -671,7 +685,7 @@ void CheckBufferOverrunImpl::bufferOverflow()
if (argtok->valueType() && argtok->valueType()->pointer == 0)
continue;
// TODO: strcpy(buf+10, "hello");
const ValueFlow::Value bufferSize = getBufferSize(argtok);
const ValueFlow::Value bufferSize = getBufferSize(argtok, mSettings);
if (bufferSize.intvalue <= 0)
continue;
// buffer size == 1 => do not warn for dynamic memory
Expand Down Expand Up @@ -782,7 +796,7 @@ void CheckBufferOverrunImpl::stringNotZeroTerminated()
const Token *sizeToken = args[2];
if (!sizeToken->hasKnownIntValue())
continue;
const ValueFlow::Value &bufferSize = getBufferSize(args[0]);
const ValueFlow::Value &bufferSize = getBufferSize(args[0], mSettings);
if (bufferSize.intvalue < 0 || sizeToken->getKnownIntValue() < bufferSize.intvalue)
continue;
if (Token::simpleMatch(args[1], "(") && Token::simpleMatch(args[1]->astOperand1(), ". c_str") && args[1]->astOperand1()->astOperand1()) {
Expand Down
2 changes: 1 addition & 1 deletion lib/checkbufferoverrun.h
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ class CPPCHECKLIB CheckBufferOverrunImpl : public CheckImpl
void objectIndex();
void objectIndexError(const Token *tok, const ValueFlow::Value *v, bool known);

ValueFlow::Value getBufferSize(const Token *bufTok) const;
ValueFlow::Value getBufferSize(const Token *bufTok, const Settings& settings) const;

// CTU
static bool isCtuUnsafeBufferUsage(const Settings &settings, const Token *argtok, CTU::FileInfo::Value *offset, int type);
Expand Down
6 changes: 6 additions & 0 deletions test/testbufferoverrun.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3545,6 +3545,12 @@ class TestBufferOverrun : public TestFixture {
" std::memset(&buf[0], 0, 25);\n"
"}\n");
ASSERT_EQUALS("", errout_str());

check("void f() {\n" // #14859
" std::vector<char> buf(25);\n"
" std::memset(&buf[0], 0, 26);\n"
"}\n");
ASSERT_EQUALS("[test.cpp:3:17]: (error) Buffer is accessed out of bounds: &buf[0] [bufferAccessOutOfBounds]\n", errout_str());
}

void buffer_overrun_errorpath() {
Expand Down
Loading