From d12732adfb0716792d635d34f760f42066dbe025 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Marjam=C3=A4ki?= Date: Sun, 6 Dec 2020 17:44:07 +0100 Subject: [PATCH] Bug hunting; Diagnose array index out of bounds when struct member is accessed --- lib/exprengine.cpp | 6 +++--- test/testbughuntingchecks.cpp | 15 ++++++++++++++- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/lib/exprengine.cpp b/lib/exprengine.cpp index 8fbee8145..b5f18fbee 100644 --- a/lib/exprengine.cpp +++ b/lib/exprengine.cpp @@ -2011,12 +2011,12 @@ static ExprEngine::ValuePtr executeCast(const Token *tok, Data &data) static ExprEngine::ValuePtr executeDot(const Token *tok, Data &data) { - if (!tok->astOperand1() || !tok->astOperand1()->varId()) { - auto v = getValueRangeFromValueType(tok->valueType(), data); + if (!tok->astOperand1()) { + auto v = std::make_shared(); call(data.callbacks, tok, v, &data); return v; } - std::shared_ptr structValue = std::dynamic_pointer_cast(data.getValue(tok->astOperand1()->varId(), nullptr, nullptr)); + std::shared_ptr structValue = std::dynamic_pointer_cast(executeExpression(tok->astOperand1(), data)); if (!structValue) { if (tok->originalName() == "->") { std::shared_ptr pointerValue = std::dynamic_pointer_cast(data.getValue(tok->astOperand1()->varId(), nullptr, nullptr)); diff --git a/test/testbughuntingchecks.cpp b/test/testbughuntingchecks.cpp index ebcaae6de..5d7204fe8 100644 --- a/test/testbughuntingchecks.cpp +++ b/test/testbughuntingchecks.cpp @@ -38,6 +38,7 @@ private: TEST_CASE(checkAssignment); TEST_CASE(arrayIndexOutOfBounds1); TEST_CASE(arrayIndexOutOfBounds2); + TEST_CASE(arrayIndexOutOfBounds3); TEST_CASE(bufferOverflowMemCmp1); TEST_CASE(bufferOverflowMemCmp2); TEST_CASE(bufferOverflowStrcpy1); @@ -83,7 +84,7 @@ private: errout.str()); } - void arrayIndexOutOfBounds2() { + void arrayIndexOutOfBounds2() { // loop check("void foo(int n) {\n" " int p[8];\n" " for (int i = 0; i < n; i++)\n" @@ -106,6 +107,18 @@ private: errout.str()); } + void arrayIndexOutOfBounds3() { // struct + check("struct S { int x; };\n" + "void foo(short i) {\n" + " S s[8];\n" + " if (s[i].x == 0) {}\n" + "}"); + ASSERT_EQUALS("[test.cpp:4]: (error) Array index out of bounds, cannot determine that i is less than 8\n" + "[test.cpp:4]: (error) Array index out of bounds, cannot determine that i is not negative\n" + "[test.cpp:4]: (error) Cannot determine that 's[i]' is initialized\n", + errout.str()); + } + void bufferOverflowMemCmp1() { // CVE-2020-24265 check("void foo(const char *pktdata, int datalen) {\n"