Travis: Run TestExprEngine tests

This commit is contained in:
Daniel Marjamäki 2020-05-08 12:21:10 +02:00
parent 93d9f38dc8
commit 02d88cb191
3 changed files with 136 additions and 143 deletions

View File

@ -63,7 +63,8 @@ matrix:
compiler: gcc compiler: gcc
script: script:
- make clean - make clean
- make USE_Z3=yes -j2 - make USE_Z3=yes -j2 all
- ./testrunner TestExprEngine
- python3 test/bug-hunting/cve.py - python3 test/bug-hunting/cve.py
- git clone https://github.com/regehr/itc-benchmarks.git ~/itc - git clone https://github.com/regehr/itc-benchmarks.git ~/itc
- python3 test/bug-hunting/itc.py - python3 test/bug-hunting/itc.py

View File

@ -1164,19 +1164,19 @@ std::string ExprEngine::BinOpResult::getExpr(ExprEngine::DataBase *dataBase) con
os << solver; os << solver;
switch (solver.check()) { switch (solver.check()) {
case z3::sat: case z3::sat:
os << "z3::sat"; os << "\nz3::sat\n";
break; break;
case z3::unsat: case z3::unsat:
os << "z3::unsat"; os << "\nz3::unsat\n";
break; break;
case z3::unknown: case z3::unknown:
os << "z3::unknown"; os << "\nz3::unknown\n";
break; break;
} }
return os.str(); return os.str();
} catch (const z3::exception &exception) { } catch (const z3::exception &exception) {
std::ostringstream os; std::ostringstream os;
os << "z3:" << exception; os << "\nz3:" << exception << "\n";
return os.str(); return os.str();
} }
#else #else

View File

@ -98,6 +98,36 @@ private:
#endif #endif
} }
static std::string cleanupExpr(std::string rawexpr) {
std::string ret;
std::istringstream istr(rawexpr);
std::string line;
while (std::getline(istr, line)) {
if (line.empty())
continue;
line = line.substr(line.find_first_not_of(" "));
if (line.compare(0,13,"(declare-fun ") == 0)
continue;
if (line == "(solver")
continue;
if (line.compare(0,9,"(assert (") == 0) {
line.erase(0,8);
line.erase(line.size()-1);
}
int par = 0;
for (int pos = 0; pos < line.size(); ++pos) {
if (line[pos] == '(')
par++;
else if (line[pos] == ')')
--par;
}
if (par < 0)
line.erase(line.size() - 1);
ret += line + "\n";
}
return ret;
}
std::string expr(const char code[], const std::string &binop) { std::string expr(const char code[], const std::string &binop) {
Settings settings; Settings settings;
settings.platform(cppcheck::Platform::Unix64); settings.platform(cppcheck::Platform::Unix64);
@ -111,9 +141,7 @@ private:
const auto *b = dynamic_cast<const ExprEngine::BinOpResult *>(&value); const auto *b = dynamic_cast<const ExprEngine::BinOpResult *>(&value);
if (!b) if (!b)
return; return;
if (!ret.empty()) ret += TestExprEngine::cleanupExpr(b->getExpr(dataBase));
ret += "\n";
ret += b->getExpr(dataBase);
}; };
std::vector<ExprEngine::Callback> callbacks; std::vector<ExprEngine::Callback> callbacks;
callbacks.push_back(f); callbacks.push_back(f);
@ -139,7 +167,7 @@ private:
std::string::size_type pos2 = ret.find("}", pos1); std::string::size_type pos2 = ret.find("}", pos1);
if (pos2 == std::string::npos) if (pos2 == std::string::npos)
return "Error:" + ret; return "Error:" + ret;
return ret.substr(pos1, pos2+1-pos1); return TestExprEngine::cleanupExpr(ret.substr(pos1, pos2+1-pos1));
} }
std::string getRange(const char code[], const std::string &str, int linenr = 0) { std::string getRange(const char code[], const std::string &str, int linenr = 0) {
@ -185,11 +213,10 @@ private:
" return x < 10;\n" " return x < 10;\n"
"}"; "}";
const char expected[] = "(declare-fun $1 () Int)\n" const char expected[] = "(>= $1 100)\n" // <- annotation
"(assert (>= $1 100))\n" // <- annotation "(and (>= $1 (- 32768)) (<= $1 32767))\n"
"(assert (and (>= $1 (- 32768)) (<= $1 32767)))\n" "(< $1 10)\n"
"(assert (< $1 10))\n" "z3::unsat\n";
"z3::unsat";
ASSERT_EQUALS(expected, expr(code, "<")); ASSERT_EQUALS(expected, expr(code, "<"));
} }
@ -200,11 +227,10 @@ private:
" return x < 10;\n" " return x < 10;\n"
"}"; "}";
const char expected[] = "(declare-fun $1 () Int)\n" const char expected[] = "(>= $1 100)\n" // <- annotation
"(assert (>= $1 100))\n" // <- annotation "(and (>= $1 (- 32768)) (<= $1 32767))\n"
"(assert (and (>= $1 (- 32768)) (<= $1 32767)))\n" "(< $1 10)\n"
"(assert (< $1 10))\n" "z3::unsat\n";
"z3::unsat";
ASSERT_EQUALS(expected, expr(code, "<")); ASSERT_EQUALS(expected, expr(code, "<"));
} }
@ -237,10 +263,9 @@ private:
ASSERT_EQUALS("(8)-($1)", getRange(code, "8-x")); ASSERT_EQUALS("(8)-($1)", getRange(code, "8-x"));
ASSERT_EQUALS("(declare-fun $1 () Int)\n" ASSERT_EQUALS("(and (>= $1 0) (<= $1 255))\n"
"(assert (and (>= $1 0) (<= $1 255)))\n" "(> (- 8 $1) 1000)\n"
"(assert (> (- 8 $1) 1000))\n" "z3::unsat\n",
"z3::unsat",
expr(code, ">")); expr(code, ">"));
} }
@ -250,24 +275,18 @@ private:
" c > 1000;" " c > 1000;"
"}"; "}";
ASSERT_EQUALS("(declare-fun $2 () Int)\n" ASSERT_EQUALS("(or (distinct $1 0) (distinct $2 0))\n"
"(declare-fun $1 () Int)\n" "(and (>= $3 (- 2147483648)) (<= $3 2147483647))\n"
"(declare-fun $3 () Int)\n" "(and (>= $1 0) (<= $1 1))\n"
"(assert (or (distinct $1 0) (distinct $2 0)))\n" "(and (>= $2 0) (<= $2 1))\n"
"(assert (and (>= $3 (- 2147483648)) (<= $3 2147483647)))\n" "(> $3 1000)\n"
"(assert (and (>= $1 0) (<= $1 1)))\n"
"(assert (and (>= $2 0) (<= $2 1)))\n"
"(assert (> $3 1000))\n"
"z3::sat\n" "z3::sat\n"
"(declare-fun $2 () Int)\n" "(= (ite (or (distinct $1 0) (distinct $2 0)) 1 0) 0)\n"
"(declare-fun $1 () Int)\n" "(and (>= $3 (- 2147483648)) (<= $3 2147483647))\n"
"(declare-fun $3 () Int)\n" "(and (>= $1 0) (<= $1 1))\n"
"(assert (= (ite (or (distinct $1 0) (distinct $2 0)) 1 0) 0))\n" "(and (>= $2 0) (<= $2 1))\n"
"(assert (and (>= $3 (- 2147483648)) (<= $3 2147483647)))\n" "(> $3 1000)\n"
"(assert (and (>= $1 0) (<= $1 1)))\n" "z3::sat\n",
"(assert (and (>= $2 0) (<= $2 1)))\n"
"(assert (> $3 1000))\n"
"z3::sat",
expr(code, ">")); expr(code, ">"));
} }
@ -280,13 +299,11 @@ private:
} }
void if1() { void if1() {
ASSERT_EQUALS("(declare-fun $2 () Int)\n" ASSERT_EQUALS("(< $1 $2)\n"
"(declare-fun $1 () Int)\n" "(and (>= $1 (- 2147483648)) (<= $1 2147483647))\n"
"(assert (< $1 $2))\n" "(and (>= $2 (- 2147483648)) (<= $2 2147483647))\n"
"(assert (and (>= $1 (- 2147483648)) (<= $1 2147483647)))\n" "(= $1 $2)\n"
"(assert (and (>= $2 (- 2147483648)) (<= $2 2147483647)))\n" "z3::unsat\n",
"(assert (= $1 $2))\n"
"z3::unsat",
expr("void f(int x, int y) { if (x < y) return x == y; }", "==")); expr("void f(int x, int y) { if (x < y) return x == y; }", "=="));
} }
@ -295,11 +312,10 @@ private:
" if (x > 0 && x == 20) {}\n" " if (x > 0 && x == 20) {}\n"
"}"; "}";
// In expression "x + x < 20", "x" is greater than 0 // In expression "x + x < 20", "x" is greater than 0
const char expected[] = "(declare-fun $1 () Int)\n" const char expected[] = "(> $1 0)\n"
"(assert (> $1 0))\n" "(and (>= $1 (- 2147483648)) (<= $1 2147483647))\n"
"(assert (and (>= $1 (- 2147483648)) (<= $1 2147483647)))\n" "(= $1 20)\n"
"(assert (= $1 20))\n" "z3::sat\n";
"z3::sat";
ASSERT_EQUALS(expected, expr(code, "==")); ASSERT_EQUALS(expected, expr(code, "=="));
} }
@ -308,11 +324,10 @@ private:
" if (x > 0 || x == 20) {}\n" " if (x > 0 || x == 20) {}\n"
"}"; "}";
// In expression "x + x < 20", "x" is greater than 0 // In expression "x + x < 20", "x" is greater than 0
const char expected[] = "(declare-fun $1 () Int)\n" const char expected[] = "(<= $1 0)\n"
"(assert (<= $1 0))\n" "(and (>= $1 (- 2147483648)) (<= $1 2147483647))\n"
"(assert (and (>= $1 (- 2147483648)) (<= $1 2147483647)))\n" "(= $1 20)\n"
"(assert (= $1 20))\n" "z3::unsat\n"; // "x == 20" is unsat
"z3::unsat"; // "x == 20" is unsat
ASSERT_EQUALS(expected, expr(code, "==")); ASSERT_EQUALS(expected, expr(code, "=="));
} }
@ -321,22 +336,19 @@ private:
" unsigned int z = y;" " unsigned int z = y;"
" if (x < z) { return z == 0; }\n" " if (x < z) { return z == 0; }\n"
"}"; "}";
const char expected[] = "(declare-fun $2 () Int)\n" const char expected[] = "(< $1 $2)\n"
"(declare-fun $1 () Int)\n" "(>= $2 0)\n"
"(assert (< $1 $2))\n" "(>= $1 0)\n"
"(assert (>= $2 0))\n" "(= $2 0)\n"
"(assert (>= $1 0))\n" "z3::unsat\n";
"(assert (= $2 0))\n"
"z3::unsat";
ASSERT_EQUALS(expected, expr(code, "==")); ASSERT_EQUALS(expected, expr(code, "=="));
} }
void ifelse1() { void ifelse1() {
ASSERT_EQUALS("(declare-fun $1 () Int)\n" ASSERT_EQUALS("(<= $1 5)\n"
"(assert (<= $1 5))\n" "(and (>= $1 (- 32768)) (<= $1 32767))\n"
"(assert (and (>= $1 (- 32768)) (<= $1 32767)))\n" "(= (+ $1 2) 40)\n"
"(assert (= (+ $1 2) 40))\n" "z3::unsat\n",
"z3::unsat",
expr("void f(short x) { if (x > 5) ; else if (x+2==40); }", "==")); expr("void f(short x) { if (x > 5) ; else if (x+2==40); }", "=="));
} }
@ -349,11 +361,10 @@ private:
" };\n" " };\n"
" x<=4;\n" " x<=4;\n"
"}"; "}";
ASSERT_EQUALS("(declare-fun $1 () Int)\n" ASSERT_EQUALS("(= $1 1)\n"
"(assert (= $1 1))\n" "(and (>= $1 (- 2147483648)) (<= $1 2147483647))\n"
"(assert (and (>= $1 (- 2147483648)) (<= $1 2147483647)))\n" "(= $1 3)\n"
"(assert (= $1 3))\n" "z3::unsat\n",
"z3::unsat",
expr(code, "==")); expr(code, "=="));
} }
@ -368,20 +379,16 @@ private:
" }\n" " }\n"
" p[0] = mcc == 0;\n" " p[0] = mcc == 0;\n"
"}"; "}";
ASSERT_EQUALS("(declare-fun $1 () Int)\n" // case '1' ASSERT_EQUALS("(= $1 49)\n"
"(declare-fun $2 () Int)\n" "(and (>= $2 (- 2147483648)) (<= $2 2147483647))\n"
"(assert (= $1 49))\n" "(and (>= $1 (- 128)) (<= $1 127))\n"
"(assert (and (>= $2 (- 2147483648)) (<= $2 2147483647)))\n" "(= $2 0)\n"
"(assert (and (>= $1 (- 128)) (<= $1 127)))\n"
"(assert (= $2 0))\n"
"z3::sat\n" "z3::sat\n"
"(declare-fun $1 () Int)\n" // case '3' "(= $1 51)\n"
"(declare-fun $2 () Int)\n" "(and (>= $2 (- 2147483648)) (<= $2 2147483647))\n"
"(assert (= $1 51))\n" "(and (>= $1 (- 128)) (<= $1 127))\n"
"(assert (and (>= $2 (- 2147483648)) (<= $2 2147483647)))\n" "(= $2 0)\n"
"(assert (and (>= $1 (- 128)) (<= $1 127)))\n" "z3::sat\n",
"(assert (= $2 0))\n"
"z3::sat",
expr(code, "==")); expr(code, "=="));
} }
@ -392,10 +399,9 @@ private:
" x = x + 34;\n" " x = x + 34;\n"
" x == 340;\n" " x == 340;\n"
"}"; "}";
ASSERT_EQUALS("(declare-fun $2 () Int)\n" ASSERT_EQUALS("(and (>= $2 (- 2147483648)) (<= $2 2147483647))\n"
"(assert (and (>= $2 (- 2147483648)) (<= $2 2147483647)))\n" "(= (+ $2 34) 340)\n"
"(assert (= (+ $2 34) 340))\n" "z3::sat\n",
"z3::sat",
expr(code, "==")); expr(code, "=="));
} }
@ -406,10 +412,9 @@ private:
" x++;\n" " x++;\n"
" x == 1;\n" " x == 1;\n"
"}"; "}";
ASSERT_EQUALS("(declare-fun $2 () Int)\n" ASSERT_EQUALS("(and (>= $2 (- 2147483648)) (<= $2 2147483647))\n"
"(assert (and (>= $2 (- 2147483648)) (<= $2 2147483647)))\n" "(= $2 1)\n"
"(assert (= $2 1))\n" "z3::sat\n",
"z3::sat",
expr(code, "==")); expr(code, "=="));
} }
@ -421,8 +426,8 @@ private:
" ab.a = 3;\n" " ab.a = 3;\n"
" ab.a == 0;\n" " ab.a == 0;\n"
"}"; "}";
ASSERT_EQUALS("(assert (= 3 0))\n" ASSERT_EQUALS("(= 3 0)\n"
"z3::unsat", "z3::unsat\n",
expr(code, "==")); expr(code, "=="));
} }
@ -437,25 +442,23 @@ private:
} }
void array1() { void array1() {
ASSERT_EQUALS("(assert (= 5 0))\nz3::unsat", ASSERT_EQUALS("(= 5 0)\nz3::unsat\n",
expr("int f() { int arr[10]; arr[4] = 5; return arr[4]==0; }", "==")); expr("int f() { int arr[10]; arr[4] = 5; return arr[4]==0; }", "=="));
} }
void array2() { void array2() {
ASSERT_EQUALS("(declare-fun |$3:4| () Int)\n" ASSERT_EQUALS("(and (>= |$3:4| 0) (<= |$3:4| 255))\n"
"(assert (and (>= |$3:4| 0) (<= |$3:4| 255)))\n" "(= |$3:4| 365)\n"
"(assert (= |$3:4| 365))\n" "z3::unsat\n",
"z3::unsat",
expr("void dostuff(unsigned char *); int f() { unsigned char arr[10] = \"\"; dostuff(arr); return arr[4] == 365; }", "==")); expr("void dostuff(unsigned char *); int f() { unsigned char arr[10] = \"\"; dostuff(arr); return arr[4] == 365; }", "=="));
} }
void array3() { void array3() {
const char code[] = "void f(unsigned char x) { int arr[10]; arr[4] = 43; return arr[x] == 12; }"; const char code[] = "void f(unsigned char x) { int arr[10]; arr[4] = 43; return arr[x] == 12; }";
ASSERT_EQUALS("?,43", getRange(code, "arr[x]")); ASSERT_EQUALS("?,43", getRange(code, "arr[x]"));
ASSERT_EQUALS("(declare-fun $1 () Int)\n" ASSERT_EQUALS("(and (>= $1 0) (<= $1 255))\n"
"(assert (and (>= $1 0) (<= $1 255)))\n" "(= (ite (= $1 4) 43 0) 12)\n"
"(assert (= (ite (= $1 4) 43 0) 12))\n" "z3::unsat\n",
"z3::unsat",
expr(code, "==")); expr(code, "=="));
} }
@ -491,10 +494,8 @@ private:
void floatValue3() { void floatValue3() {
const char code[] = "void foo(float f) { return f > 12.0; }"; const char code[] = "void foo(float f) { return f > 12.0; }";
const char expected[] = "(declare-fun |12.0| () Real)\n" const char expected[] = "(> $1 |12.0|)\n"
"(declare-fun $1 () Real)\n" "z3::sat\n";
"(assert (> $1 |12.0|))\n"
"z3::sat";
ASSERT_EQUALS(expected, expr(code, ">")); ASSERT_EQUALS(expected, expr(code, ">"));
} }
@ -531,22 +532,19 @@ private:
s.functionContracts["foo(x)"] = "x < 1000"; s.functionContracts["foo(x)"] = "x < 1000";
ASSERT_EQUALS("checkContract:{\n" ASSERT_EQUALS("checkContract:{\n"
" (declare-fun $2 () Int)\n" "(ite (< $2 1000) false true)\n"
" (declare-fun $1 () Int)\n" "(= $2 $1)\n"
" (assert (ite (< $2 1000) false true))\n" "(and (>= $2 (- 2147483648)) (<= $2 2147483647))\n"
" (assert (= $2 $1))\n" "(and (>= $1 0) (<= $1 65535))\n"
" (assert (and (>= $2 (- 2147483648)) (<= $2 2147483647)))\n" "}\n",
" (assert (and (>= $1 0) (<= $1 65535)))\n"
"}",
functionCallContractExpr(code, s)); functionCallContractExpr(code, s));
} }
void int1() { void int1() {
ASSERT_EQUALS("(declare-fun $1 () Int)\n" ASSERT_EQUALS("(and (>= $1 (- 2147483648)) (<= $1 2147483647))\n"
"(assert (and (>= $1 (- 2147483648)) (<= $1 2147483647)))\n" "(= (+ 2 $1) 3)\n"
"(assert (= (+ 2 $1) 3))\n" "z3::sat\n",
"z3::sat",
expr("void f(int x) { return 2+x==3; }", "==")); expr("void f(int x) { return 2+x==3; }", "=="));
} }
@ -554,19 +552,17 @@ private:
void pointer1() { void pointer1() {
const char code[] = "void f(unsigned char *p) { return *p == 7; }"; const char code[] = "void f(unsigned char *p) { return *p == 7; }";
ASSERT_EQUALS("size=$1,[:]=?,null", getRange(code, "p")); ASSERT_EQUALS("size=$1,[:]=?,null", getRange(code, "p"));
ASSERT_EQUALS("(declare-fun $3 () Int)\n" ASSERT_EQUALS("(and (>= $3 0) (<= $3 255))\n"
"(assert (and (>= $3 0) (<= $3 255)))\n" "(= $3 7)\n"
"(assert (= $3 7))\n" "z3::sat\n",
"z3::sat",
expr(code, "==")); expr(code, "=="));
} }
void pointer2() { void pointer2() {
const char code[] = "void f(unsigned char *p) { return p[2] == 7; }"; const char code[] = "void f(unsigned char *p) { return p[2] == 7; }";
ASSERT_EQUALS("(declare-fun $3 () Int)\n" ASSERT_EQUALS("(and (>= $3 0) (<= $3 255))\n"
"(assert (and (>= $3 0) (<= $3 255)))\n" "(= $3 7)\n"
"(assert (= $3 7))\n" "z3::sat\n",
"z3::sat",
expr(code, "==")); expr(code, "=="));
} }
@ -597,12 +593,10 @@ private:
void structMember1() { void structMember1() {
ASSERT_EQUALS("(declare-fun $2 () Int)\n" ASSERT_EQUALS("(and (>= $2 0) (<= $2 255))\n"
"(declare-fun $3 () Int)\n" "(and (>= $3 0) (<= $3 255))\n"
"(assert (and (>= $2 0) (<= $2 255)))\n" "(= (+ $2 $3) 0)\n"
"(assert (and (>= $3 0) (<= $3 255)))\n" "z3::sat\n",
"(assert (= (+ $2 $3) 0))\n"
"z3::sat",
expr("struct S {\n" expr("struct S {\n"
" unsigned char a;\n" " unsigned char a;\n"
" unsigned char b;\n" " unsigned char b;\n"
@ -614,10 +608,9 @@ private:
const char code[] = "struct S { int x; };\n" const char code[] = "struct S { int x; };\n"
"void foo(struct S *s) { return s->x == 123; }"; "void foo(struct S *s) { return s->x == 123; }";
const char expected[] = "(declare-fun $3 () Int)\n" const char expected[] = "(and (>= $3 (- 2147483648)) (<= $3 2147483647))\n"
"(assert (and (>= $3 (- 2147483648)) (<= $3 2147483647)))\n" "(= $3 123)\n"
"(assert (= $3 123))\n" "z3::sat\n";
"z3::sat";
ASSERT_EQUALS(expected, expr(code, "==")); ASSERT_EQUALS(expected, expr(code, "=="));
} }
@ -629,10 +622,9 @@ private:
" return s->x == 1;\n" " return s->x == 1;\n"
"}"; "}";
const char expected[] = "(declare-fun $3 () Int)\n" const char expected[] = "(and (>= $3 (- 2147483648)) (<= $3 2147483647))\n"
"(assert (and (>= $3 (- 2147483648)) (<= $3 2147483647)))\n" "(= $3 1)\n"
"(assert (= $3 1))\n" "z3::sat\n";
"z3::sat";
ASSERT_EQUALS(expected, expr(code, "==")); ASSERT_EQUALS(expected, expr(code, "=="));
} }