diff --git a/lib/checkbufferoverrun.cpp b/lib/checkbufferoverrun.cpp index 246d428802e..46d8e1c7c6c 100644 --- a/lib/checkbufferoverrun.cpp +++ b/lib/checkbufferoverrun.cpp @@ -560,12 +560,18 @@ ValueFlow::Value CheckBufferOverrunImpl::getBufferSize(const Token *bufTok, cons if (!bufTok->valueType()) return ValueFlow::Value(-1); + MathLib::bigint index = 0; if (bufTok->isUnaryOp("&")) { bufTok = bufTok->astOperand1(); if (Token::simpleMatch(bufTok, "[")) { - const Token* index = bufTok->astOperand2(); - if (!(index && index->hasKnownIntValue() && index->getKnownIntValue() == 0)) - return ValueFlow::Value(-1); + if (const Token* indexTok = bufTok->astOperand2()) { + if (indexTok->hasKnownIntValue()) + index = indexTok->getKnownIntValue(); + else if (const ValueFlow::Value* maxValue = indexTok->getMaxValue(false)) + index = maxValue->intvalue; + else + return ValueFlow::Value(-1); + } bufTok = bufTok->astOperand1(); } } @@ -600,10 +606,10 @@ ValueFlow::Value CheckBufferOverrunImpl::getBufferSize(const Token *bufTok, cons v.valueType = ValueFlow::Value::ValueType::BUFFER_SIZE; if (var->isPointerArray()) - v.intvalue = dim * mSettings.platform.sizeof_pointer; + v.intvalue = (dim - index) * mSettings.platform.sizeof_pointer; else { const size_t typeSize = bufTok->valueType()->getSizeOf(mSettings, ValueType::Accuracy::ExactOrZero, ValueType::SizeOf::Pointee); - v.intvalue = dim * typeSize; + v.intvalue = (dim - index) * typeSize; } return v; diff --git a/test/testbufferoverrun.cpp b/test/testbufferoverrun.cpp index b44fd742ab1..37ab7083902 100644 --- a/test/testbufferoverrun.cpp +++ b/test/testbufferoverrun.cpp @@ -3537,7 +3537,7 @@ class TestBufferOverrun : public TestFixture { "}\n"); TODO_ASSERT_EQUALS("[test.cpp:3:12]: (error) Buffer is accessed out of bounds: &a[5] [bufferAccessOutOfBounds]\n" "[test.cpp:7:12]: (error) Buffer is accessed out of bounds: &a[0][0] [bufferAccessOutOfBounds]\n", - "", + "[test.cpp:3:12]: (error) Buffer is accessed out of bounds: &a[5] [bufferAccessOutOfBounds]\n", errout_str()); check("void f() {\n" // #14866 @@ -3557,6 +3557,13 @@ class TestBufferOverrun : public TestFixture { " fwrite(&s, 1, 1, fp);\n" "}\n"); ASSERT_EQUALS("", errout_str()); // don't crash + + check("void f() {\n" // #14935 + " int a[5];\n" + " for (int i = 0; i < 5; ++i)\n" + " memset(&a[i], 0, sizeof(a));\n" + "}\n"); + ASSERT_EQUALS("[test.cpp:4:16]: (error) Buffer is accessed out of bounds: &a[i] [bufferAccessOutOfBounds]\n", errout_str()); } void buffer_overrun_errorpath() { @@ -3814,7 +3821,7 @@ class TestBufferOverrun : public TestFixture { " int i[10];\n" " memset(&i[1], 0, 1000);\n" "}"); - TODO_ASSERT_EQUALS("[test.cpp:3:10]: (error) Buffer is accessed out of bounds: &i[1] [bufferAccessOutOfBounds]\n", "", errout_str()); + ASSERT_EQUALS("[test.cpp:3:10]: (error) Buffer is accessed out of bounds: &i[1] [bufferAccessOutOfBounds]\n", errout_str()); check("struct S { int x; };\n" // #8616 "void f() {\n"