Bug hunting; better handling when assigning multidimensional array in for loop

This commit is contained in:
Daniel Marjamäki 2020-06-15 22:42:45 +02:00
parent b36c85d8fd
commit 6faad9cd90
2 changed files with 29 additions and 10 deletions

View File

@ -1929,8 +1929,13 @@ static void execute(const Token *start, const Token *end, Data &data, int recurs
std::set<int> 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<ExprEngine::ArrayValue>(val);
//ExprEngine::ValuePtr anyValue = getValueRangeFromValueType(data.getNewSymbolName(), tok2->astOperand1()->valueType(), *data.settings);
arrayValue->assign(std::make_shared<ExprEngine::IntRange>("0", 0, 0), std::make_shared<ExprEngine::BailoutValue>());
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<ExprEngine::ArrayValue>(oldValue);
arrayValue->assign(std::make_shared<ExprEngine::IntRange>(data.getNewSymbolName(), 0, ~0ULL), std::make_shared<ExprEngine::BailoutValue>());
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();

View File

@ -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"));