diff --git a/lib/checkbufferoverrun.cpp b/lib/checkbufferoverrun.cpp index d278208fcc3..8be9b508849 100644 --- a/lib/checkbufferoverrun.cpp +++ b/lib/checkbufferoverrun.cpp @@ -556,8 +556,16 @@ ValueFlow::Value CheckBufferOverrunImpl::getBufferSize(const Token *bufTok) cons { if (!bufTok->valueType()) return ValueFlow::Value(-1); - if (bufTok->isUnaryOp("&")) + + 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); + bufTok = bufTok->astOperand1(); + } + } const Variable *var = bufTok->variable(); if (!var || var->dimensions().empty()) { diff --git a/test/testbufferoverrun.cpp b/test/testbufferoverrun.cpp index 23e55748ce6..1a03ca336f8 100644 --- a/test/testbufferoverrun.cpp +++ b/test/testbufferoverrun.cpp @@ -227,6 +227,7 @@ class TestBufferOverrun : public TestFixture { TEST_CASE(buffer_overrun_35); //#2304 TEST_CASE(buffer_overrun_36); TEST_CASE(buffer_overrun_37); + TEST_CASE(buffer_overrun_38); TEST_CASE(buffer_overrun_errorpath); TEST_CASE(buffer_overrun_bailoutIfSwitch); // ticket #2378 : bailoutIfSwitch TEST_CASE(buffer_overrun_function_array_argument); @@ -3507,6 +3508,39 @@ class TestBufferOverrun : public TestFixture { ASSERT_EQUALS("", errout_str()); } + void buffer_overrun_38() { // #9173 + check("void f() {\n" + " int a[10];\n" + " memset(&a[0], 0, 20 * sizeof(int));\n" + "}\n" + "void g() {\n" + " int a[10];\n" + " memset(&a[0], 0, 10 * sizeof(int));\n" + "}\n" + "void h() {\n" + " int a[10];\n" + " memset(&a[5], 0, 5 * sizeof(int));\n" + "}\n" + "void i() {\n" + " int a[10][10];\n" + " memset(&a[0][0], 0, 100 * sizeof(int));\n" + "}\n"); + ASSERT_EQUALS("[test.cpp:3:12]: (error) Buffer is accessed out of bounds: &a[0] [bufferAccessOutOfBounds]\n", errout_str()); + + check("void f() {\n" + " int a[10];\n" + " memset(&a[5], 0, 10 * sizeof(int));\n" + "}\n" + "void g() {\n" + " int a[1][1];\n" + " memset(&a[0][0], 0, 10 * sizeof(int));\n" + "}\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", + "", + errout_str()); + } + void buffer_overrun_errorpath() { setMultiline(); Settings s = settings0;