/* Boolector: Satisfiability Modulo Theories (SMT) solver. * * Copyright (C) 2007-2021 by the authors listed in the AUTHORS file. * * This file is part of Boolector. * See COPYING for more information on using this software. */ #include "test.h" extern "C" { #include "btoraig.h" #include "dumper/btordumpaig.h" #include "utils/btorutil.h" } class TestOverflow : public TestBtor { protected: static constexpr uint32_t BTOR_TEST_OVERFLOW_LOW = 1; static constexpr uint32_t BTOR_TEST_OVERFLOW_HIGH = 4; enum Op { UADD, SADD, USUB, SSUB, UMUL, SMUL, SDIV }; int32_t add (int32_t x, int32_t y) { return x + y; } int32_t sub (int32_t x, int32_t y) { return x - y; } int32_t mul (int32_t x, int32_t y) { return x * y; } int32_t div (int32_t x, int32_t y) { assert (y != 0); return x / y; } void u_overflow_test (Op op, int32_t low, int32_t high, uint32_t rwl) { assert (low > 0); assert (low <= high); BoolectorNode *(*btor_fun) (Btor *, BoolectorNode *, BoolectorNode *); int32_t i, j, num_bits, max, result; bool overflow_test, overflow_boolector; int32_t sat_res; for (num_bits = low; num_bits <= high; num_bits++) { max = btor_util_pow_2 (num_bits); for (i = 0; i < max; i++) { for (j = 0; j < max; j++) { BoolectorSort sort; BoolectorNode *const1, *const2, *bfun; if (d_btor) boolector_delete (d_btor); d_btor = boolector_new (); boolector_set_opt (d_btor, BTOR_OPT_REWRITE_LEVEL, rwl); overflow_test = false; overflow_boolector = false; switch (op) { case UADD: btor_fun = boolector_uaddo; result = add (i, j); break; case SADD: btor_fun = boolector_saddo; result = add (i, j); break; case USUB: btor_fun = boolector_usubo; result = sub (i, j); break; case SSUB: btor_fun = boolector_ssubo; result = sub (i, j); break; case UMUL: btor_fun = boolector_umulo; result = mul (i, j); break; case SMUL: btor_fun = boolector_smulo; result = mul (i, j); break; default: assert (op == SDIV); btor_fun = boolector_sdivo; result = div (i, j); } if (result < 0 || result >= max) overflow_test = true; sort = boolector_bitvec_sort (d_btor, num_bits); const1 = boolector_unsigned_int (d_btor, i, sort); const2 = boolector_unsigned_int (d_btor, j, sort); bfun = btor_fun (d_btor, const1, const2); boolector_assert (d_btor, bfun); sat_res = boolector_sat (d_btor); ASSERT_TRUE (sat_res == BOOLECTOR_SAT || sat_res == BOOLECTOR_UNSAT); if (sat_res == BOOLECTOR_SAT) { overflow_boolector = true; } if (overflow_boolector) { ASSERT_TRUE (overflow_test); } if (overflow_test) { ASSERT_TRUE (overflow_boolector); } boolector_release_sort (d_btor, sort); boolector_release (d_btor, const1); boolector_release (d_btor, const2); boolector_release (d_btor, bfun); boolector_delete (d_btor); d_btor = nullptr; } } } } void s_overflow_test ( Op op, bool exclude_second_zero, int32_t low, int32_t high, uint32_t rwl) { assert (low > 0); assert (low <= high); BoolectorNode *(*btor_fun) (Btor *, BoolectorNode *, BoolectorNode *); int32_t i, j; bool overflow_test, overflow_boolector; int32_t result, num_bits, max; int32_t sat_res; for (num_bits = low; num_bits <= high; num_bits++) { max = btor_util_pow_2 (num_bits - 1); for (i = -max; i < max; i++) { for (j = -max; j < max; j++) { if (!exclude_second_zero || j != 0) { BoolectorSort sort; BoolectorNode *const1, *const2, *bfun; if (d_btor) boolector_delete (d_btor); d_btor = boolector_new (); boolector_set_opt (d_btor, BTOR_OPT_REWRITE_LEVEL, rwl); overflow_test = false; overflow_boolector = false; switch (op) { case UADD: btor_fun = boolector_uaddo; result = add (i, j); break; case SADD: btor_fun = boolector_saddo; result = add (i, j); break; case USUB: btor_fun = boolector_usubo; result = sub (i, j); break; case SSUB: btor_fun = boolector_ssubo; result = sub (i, j); break; case UMUL: btor_fun = boolector_umulo; result = mul (i, j); break; case SMUL: btor_fun = boolector_smulo; result = mul (i, j); break; default: assert (op == SDIV); btor_fun = boolector_sdivo; result = div (i, j); } if (!(result >= -max && result < max)) overflow_test = true; sort = boolector_bitvec_sort (d_btor, num_bits); const1 = boolector_int (d_btor, i, sort); const2 = boolector_int (d_btor, j, sort); bfun = btor_fun (d_btor, const1, const2); boolector_assert (d_btor, bfun); sat_res = boolector_sat (d_btor); ASSERT_TRUE (sat_res == BOOLECTOR_SAT || sat_res == BOOLECTOR_UNSAT); if (sat_res == BOOLECTOR_SAT) { overflow_boolector = true; } if (overflow_boolector) { ASSERT_TRUE (overflow_test); } if (overflow_test) { ASSERT_TRUE (overflow_boolector); } boolector_release_sort (d_btor, sort); boolector_release (d_btor, const1); boolector_release (d_btor, const2); boolector_release (d_btor, bfun); boolector_delete (d_btor); d_btor = nullptr; } } } } } }; TEST_F (TestOverflow, uaddo) { u_overflow_test (UADD, BTOR_TEST_OVERFLOW_LOW, BTOR_TEST_OVERFLOW_HIGH, 1); u_overflow_test (UADD, BTOR_TEST_OVERFLOW_LOW, BTOR_TEST_OVERFLOW_HIGH, 0); } TEST_F (TestOverflow, usubo) { u_overflow_test (USUB, BTOR_TEST_OVERFLOW_LOW, BTOR_TEST_OVERFLOW_HIGH, 1); u_overflow_test (USUB, BTOR_TEST_OVERFLOW_LOW, BTOR_TEST_OVERFLOW_HIGH, 0); } TEST_F (TestOverflow, umulo) { u_overflow_test (UMUL, BTOR_TEST_OVERFLOW_LOW, BTOR_TEST_OVERFLOW_HIGH, 1); u_overflow_test (UMUL, BTOR_TEST_OVERFLOW_LOW, BTOR_TEST_OVERFLOW_HIGH, 0); } TEST_F (TestOverflow, saddo) { s_overflow_test ( SADD, false, BTOR_TEST_OVERFLOW_LOW, BTOR_TEST_OVERFLOW_HIGH, 1); s_overflow_test ( SADD, false, BTOR_TEST_OVERFLOW_LOW, BTOR_TEST_OVERFLOW_HIGH, 0); } TEST_F (TestOverflow, ssubo) { s_overflow_test ( SSUB, false, BTOR_TEST_OVERFLOW_LOW, BTOR_TEST_OVERFLOW_HIGH, 1); s_overflow_test ( SSUB, false, BTOR_TEST_OVERFLOW_LOW, BTOR_TEST_OVERFLOW_HIGH, 0); } TEST_F (TestOverflow, smulo) { s_overflow_test ( SMUL, false, BTOR_TEST_OVERFLOW_LOW, BTOR_TEST_OVERFLOW_HIGH, 1); s_overflow_test ( SMUL, false, BTOR_TEST_OVERFLOW_LOW, BTOR_TEST_OVERFLOW_HIGH, 0); } TEST_F (TestOverflow, sdivo) { s_overflow_test ( SDIV, true, BTOR_TEST_OVERFLOW_LOW, BTOR_TEST_OVERFLOW_HIGH, 1); s_overflow_test ( SDIV, true, BTOR_TEST_OVERFLOW_LOW, BTOR_TEST_OVERFLOW_HIGH, 0); }