Skip to content

Commit b1b7e3c

Browse files
Fix #14948 FP bufferAccessOutOfBounds after container size check (#8763)
Co-authored-by: chrchr-github <noreply@github.com>
1 parent 4b0c239 commit b1b7e3c

2 files changed

Lines changed: 26 additions & 2 deletions

File tree

lib/checkbufferoverrun.cpp

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,9 @@ static const ValueFlow::Value *getBufferSizeValue(const Token *tok)
6868
auto it = std::find_if(tokenValues.cbegin(), tokenValues.cend(), std::mem_fn(&ValueFlow::Value::isBufferSizeValue));
6969
if (it != tokenValues.cend())
7070
return &*it;
71-
it = std::find_if(tokenValues.cbegin(), tokenValues.cend(), std::mem_fn(&ValueFlow::Value::isContainerSizeValue));
71+
it = std::find_if(tokenValues.cbegin(), tokenValues.cend(), [](const ValueFlow::Value& v) {
72+
return v.isContainerSizeValue() && !v.isImpossible();
73+
});
7274
return it == tokenValues.cend() ? nullptr : &*it;
7375
}
7476

@@ -597,6 +599,8 @@ ValueFlow::Value CheckBufferOverrunImpl::getBufferSize(const Token *bufTok, cons
597599
ValueFlow::Value bufSizeVal;
598600
bufSizeVal.valueType = ValueFlow::Value::ValueType::BUFFER_SIZE;
599601
bufSizeVal.intvalue = value->intvalue * elementSize;
602+
bufSizeVal.valueKind = value->valueKind;
603+
bufSizeVal.errorPath = value->errorPath;
600604
return bufSizeVal;
601605
}
602606
}
@@ -730,7 +734,10 @@ void CheckBufferOverrunImpl::bufferOverflow()
730734

731735
void CheckBufferOverrunImpl::bufferOverflowError(const Token *tok, const ValueFlow::Value *value, Certainty certainty)
732736
{
733-
reportError(getErrorPath(tok, value, "Buffer overrun"), Severity::error, "bufferAccessOutOfBounds", "Buffer is accessed out of bounds: " + (tok ? getRealBufferTok(tok)->expressionString() : "buf"), CWE_BUFFER_OVERRUN, certainty);
737+
const auto errorPath = getErrorPath(tok, value, "Buffer overrun");
738+
const auto severity = !value || value->isKnown() ? Severity::error : Severity::warning;
739+
const std::string msg = "Buffer is accessed out of bounds: " + (tok ? getRealBufferTok(tok)->expressionString() : "buf");
740+
reportError(errorPath, severity, "bufferAccessOutOfBounds", msg, CWE_BUFFER_OVERRUN, certainty);
734741
}
735742

736743
//---------------------------------------------------------------------------

test/testbufferoverrun.cpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3628,6 +3628,14 @@ class TestBufferOverrun : public TestFixture {
36283628
" memset(&a[i], 0, sizeof(a));\n"
36293629
"}\n");
36303630
ASSERT_EQUALS("[test.cpp:4:16]: (error) Buffer is accessed out of bounds: &a[i] [bufferAccessOutOfBounds]\n", errout_str());
3631+
3632+
check("void f(const std::vector<uint8_t>& s) {\n" // #14948
3633+
" if (s.size() < 4)\n"
3634+
" return;\n"
3635+
" uint32_t u = 0;\n"
3636+
" std::memcpy(&u, &s[0], sizeof(u));\n"
3637+
"}\n");
3638+
ASSERT_EQUALS("", errout_str());
36313639
}
36323640

36333641
void buffer_overrun_errorpath() {
@@ -3642,6 +3650,15 @@ class TestBufferOverrun : public TestFixture {
36423650
ASSERT_EQUALS("[test.cpp:3:12]: error: Buffer is accessed out of bounds: p [bufferAccessOutOfBounds]\n"
36433651
"[test.cpp:2:13]: note: Assign p, buffer with size 10\n"
36443652
"[test.cpp:3:12]: note: Buffer overrun\n", errout_str());
3653+
3654+
check("void f(const std::vector<uint8_t>& s) {\n"
3655+
" if (s.size() == 2) {}\n"
3656+
" uint32_t u = 0;\n"
3657+
" std::memcpy(&u, &s[0], sizeof(u));\n"
3658+
"}\n", s);
3659+
ASSERT_EQUALS("[test.cpp:4:21]: warning: Buffer is accessed out of bounds: &s[0] [bufferAccessOutOfBounds]\n"
3660+
"[test.cpp:2:18]: note: Assuming that condition 's.size()==2' is not redundant\n"
3661+
"[test.cpp:4:21]: note: Buffer overrun\n", errout_str());
36453662
}
36463663

36473664
void buffer_overrun_bailoutIfSwitch() {

0 commit comments

Comments
 (0)