ValueFlow: improved abstract interpretation of for loops

This commit is contained in:
Daniel Marjamäki 2014-03-24 00:16:02 +01:00
parent c14a3d67bb
commit dbc8273cb7
3 changed files with 15 additions and 11 deletions

View File

@ -655,7 +655,7 @@ static void execute(const Token *expr,
*error = true; *error = true;
} }
else if (expr->str() == "++") { else if (expr->str() == "++" || expr->str() == "--") {
if (!expr->astOperand1() || expr->astOperand1()->varId() == 0U) if (!expr->astOperand1() || expr->astOperand1()->varId() == 0U)
*error = true; *error = true;
else { else {
@ -663,7 +663,7 @@ static void execute(const Token *expr,
if (var == programMemory->end()) if (var == programMemory->end())
*error = true; *error = true;
else { else {
*result = var->second + 1; *result = var->second + (expr->str() == "++" ? 1 : -1);
var->second = *result; var->second = *result;
} }
} }
@ -757,8 +757,7 @@ static bool valueFlowForLoop2(const Token *tok,
if (error) if (error)
return false; return false;
execute(secondExpression, &programMemory, &result, &error); execute(secondExpression, &programMemory, &result, &error);
if (error)
return false;
std::map<unsigned int, MathLib::bigint> startMemory(programMemory); std::map<unsigned int, MathLib::bigint> startMemory(programMemory);
std::map<unsigned int, MathLib::bigint> endMemory; std::map<unsigned int, MathLib::bigint> endMemory;
@ -771,9 +770,10 @@ static bool valueFlowForLoop2(const Token *tok,
} }
memory1->swap(startMemory); memory1->swap(startMemory);
memory2->swap(endMemory); if (!error)
memory2->swap(endMemory);
return !error; return true;
} }
static void valueFlowForLoopSimplify(Token * const bodyStart, const unsigned int varid, const MathLib::bigint value, TokenList *tokenlist, ErrorLogger *errorLogger, const Settings *settings) static void valueFlowForLoopSimplify(Token * const bodyStart, const unsigned int varid, const MathLib::bigint value, TokenList *tokenlist, ErrorLogger *errorLogger, const Settings *settings)

View File

@ -1047,7 +1047,8 @@ private:
" for (int i = 3; 0 <= i; i--)\n" " for (int i = 3; 0 <= i; i--)\n"
" a[i] = i;\n" " a[i] = i;\n"
"}"); "}");
ASSERT_EQUALS("[test.cpp:5]: (error) Buffer is accessed out of bounds: a\n", errout.str()); ASSERT_EQUALS("[test.cpp:5]: (error) Buffer is accessed out of bounds: a\n"
"[test.cpp:5]: (error) Array 'a[3]' accessed at index 3, which is out of bounds.\n", errout.str());
check("void f()\n" check("void f()\n"
"{\n" "{\n"
@ -1536,7 +1537,8 @@ private:
" buffer[i] = i;\n" " buffer[i] = i;\n"
" }\n" " }\n"
"}"); "}");
ASSERT_EQUALS("[test.cpp:5]: (error) Buffer is accessed out of bounds: buffer\n", errout.str()); ASSERT_EQUALS("[test.cpp:5]: (error) Buffer is accessed out of bounds: buffer\n"
"[test.cpp:5]: (error) Array 'buffer[9]' accessed at index 9, which is out of bounds.\n", errout.str());
// Correct access limits -> i from 9 to 0 // Correct access limits -> i from 9 to 0
check("void f() {\n" check("void f() {\n"
@ -1768,7 +1770,8 @@ private:
" data[i] = 0;\n" " data[i] = 0;\n"
" }\n" " }\n"
"}"); "}");
ASSERT_EQUALS("[test.cpp:5]: (error) Buffer is accessed out of bounds: data\n", errout.str()); ASSERT_EQUALS("[test.cpp:5]: (error) Buffer is accessed out of bounds: data\n"
"[test.cpp:5]: (error) Array 'data[8]' accessed at index 10, which is out of bounds.\n", errout.str());
check("void f()\n" check("void f()\n"
"{\n" "{\n"
@ -1902,7 +1905,8 @@ private:
" a[i] = 0;\n" " a[i] = 0;\n"
" }\n" " }\n"
"}"); "}");
ASSERT_EQUALS("[test.cpp:4]: (error) Buffer is accessed out of bounds: a\n", errout.str()); ASSERT_EQUALS("[test.cpp:4]: (error) Buffer is accessed out of bounds: a\n"
"[test.cpp:4]: (error) Array 'a[10]' accessed at index 10, which is out of bounds.\n", errout.str());
} }
void array_index_for_neq() { void array_index_for_neq() {

View File

@ -645,7 +645,7 @@ private:
" for (int x = 0; x < 10; x = x / 0)\n" " for (int x = 0; x < 10; x = x / 0)\n"
" a[x] = 0;\n" " a[x] = 0;\n"
"}"; "}";
testValueOfX(code, 3U, 0); // don't crash ASSERT_EQUALS(true, testValueOfX(code, 3U, 0)); // don't crash
code = "void f() {\n" code = "void f() {\n"
" for (int x = 0; x < 10; x++)\n" " for (int x = 0; x < 10; x++)\n"