From 6faad9cd90b75c6af0a8b8411ecce64253a800b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Marjam=C3=A4ki?= Date: Mon, 15 Jun 2020 22:42:45 +0200 Subject: [PATCH] Bug hunting; better handling when assigning multidimensional array in for loop --- lib/exprengine.cpp | 29 +++++++++++++++++++---------- test/testexprengine.cpp | 10 ++++++++++ 2 files changed, 29 insertions(+), 10 deletions(-) diff --git a/lib/exprengine.cpp b/lib/exprengine.cpp index 8beaf04fe..94f307a9f 100644 --- a/lib/exprengine.cpp +++ b/lib/exprengine.cpp @@ -1929,8 +1929,13 @@ static void execute(const Token *start, const Token *end, Data &data, int recurs std::set changedVariables; for (const Token *tok2 = tok; tok2 != bodyEnd; tok2 = tok2->next()) { if (Token::Match(tok2, "%assign%")) { - if (Token::Match(tok2->astOperand1(), ". %name% =") && tok2->astOperand1()->astOperand1() && tok2->astOperand1()->astOperand1()->valueType()) { - const Token *structToken = tok2->astOperand1()->astOperand1(); + const Token *lhs = tok2->astOperand1(); + while (Token::simpleMatch(lhs, "[")) + lhs = lhs->astOperand1(); + if (!lhs) + throw BugHuntingException(tok2, "Unhandled assignment in loop"); + if (Token::Match(lhs, ". %name% =|[") && lhs->astOperand1() && lhs->astOperand1()->valueType()) { + const Token *structToken = lhs->astOperand1(); if (!structToken->valueType() || !structToken->varId()) throw BugHuntingException(tok2, "Unhandled assignment in loop"); const Scope *structScope = structToken->valueType()->typeScope; @@ -1957,30 +1962,34 @@ static void execute(const Token *start, const Token *end, Data &data, int recurs data.assignStructMember(tok2, &*structVal, memberName, memberValue); continue; } - if (tok2->astOperand1() && tok2->astOperand1()->isUnaryOp("*") && tok2->astOperand1()->astOperand1()->varId()) { + if (lhs->isUnaryOp("*") && lhs->astOperand1()->varId()) { const Token *varToken = tok2->astOperand1()->astOperand1(); ExprEngine::ValuePtr val = data.getValue(varToken->varId(), varToken->valueType(), varToken); if (val && val->type == ExprEngine::ValueType::ArrayValue) { // Try to assign "any" value auto arrayValue = std::dynamic_pointer_cast(val); - //ExprEngine::ValuePtr anyValue = getValueRangeFromValueType(data.getNewSymbolName(), tok2->astOperand1()->valueType(), *data.settings); arrayValue->assign(std::make_shared("0", 0, 0), std::make_shared()); continue; } } - if (!Token::Match(tok2->astOperand1(), "%var%")) - throw BugHuntingException(tok2, "Unhandled assignment in loop"); - if (!tok2->astOperand1()->variable()) + if (!lhs->variable()) throw BugHuntingException(tok2, "Unhandled assignment in loop"); // give variable "any" value - int varid = tok2->astOperand1()->varId(); + int varid = lhs->varId(); if (changedVariables.find(varid) != changedVariables.end()) continue; changedVariables.insert(varid); auto oldValue = data.getValue(varid, nullptr, nullptr); if (oldValue && oldValue->isUninit()) - call(data.callbacks, tok2->astOperand1(), oldValue, &data); - data.assignValue(tok2, varid, getValueRangeFromValueType(data.getNewSymbolName(), tok2->astOperand1()->valueType(), *data.settings)); + call(data.callbacks, lhs, oldValue, &data); + if (oldValue && oldValue->type == ExprEngine::ValueType::ArrayValue) { + // Try to assign "any" value + auto arrayValue = std::dynamic_pointer_cast(oldValue); + arrayValue->assign(std::make_shared(data.getNewSymbolName(), 0, ~0ULL), std::make_shared()); + continue; + } + data.assignValue(tok2, varid, getValueRangeFromValueType(data.getNewSymbolName(), lhs->valueType(), *data.settings)); + continue; } else if (Token::Match(tok2, "++|--") && tok2->astOperand1() && tok2->astOperand1()->variable()) { // give variable "any" value const Token *vartok = tok2->astOperand1(); diff --git a/test/testexprengine.cpp b/test/testexprengine.cpp index 5b5a0a532..dcb80812d 100644 --- a/test/testexprengine.cpp +++ b/test/testexprengine.cpp @@ -73,6 +73,7 @@ private: TEST_CASE(arrayInit1); TEST_CASE(arrayInit2); TEST_CASE(arrayUninit); + TEST_CASE(arrayInLoop); TEST_CASE(floatValue1); TEST_CASE(floatValue2); @@ -524,6 +525,15 @@ private: ASSERT_EQUALS("?", getRange("int f() { int arr[10]; return arr[4]; }", "arr[4]")); } + void arrayInLoop() { + const char code[] = "void f() {\n" + " int arr[3][3];\n" + " for (int i = 0; i < 3; i++) arr[i][0] = arr[1][2];\n" + " return arr[0][0];" + "}"; + ASSERT_EQUALS("?", getRange(code, "arr[1]")); + } + void floatValue1() { ASSERT_EQUALS("-inf:inf", getRange("float f; void func() { f=f; }", "f=f"));