From 3f51807f24c9132d673abcaf02f288d9bf592825 Mon Sep 17 00:00:00 2001 From: Andrey Semashev Date: Thu, 16 Sep 2021 02:12:41 +0300 Subject: [PATCH] Disabled random operators tests under UBSAN. The tests use random input to various arithmetic and bitwise operators, which cause undefined behavior, such as shifting by more than the left operand capacity or signed integer overflows. --- test/operators_test.cpp | 126 ++++++++++++++++++++-------------------- 1 file changed, 64 insertions(+), 62 deletions(-) diff --git a/test/operators_test.cpp b/test/operators_test.cpp index c1edf8f..7e77261 100644 --- a/test/operators_test.cpp +++ b/test/operators_test.cpp @@ -28,7 +28,6 @@ #include // for std::cout (std::endl indirectly) - namespace { // avoiding a template version of true_value so as to not confuse VC++ @@ -71,7 +70,7 @@ namespace { return _value < x._value; } convertible_to_bool operator==(const Wrapped1& x) const { return _value == x._value; } - + Wrapped1& operator+=(const Wrapped1& x) { _value += x._value; return *this; } Wrapped1& operator-=(const Wrapped1& x) @@ -94,12 +93,12 @@ namespace { _value >>= x._value; return *this; } Wrapped1& operator++() { ++_value; return *this; } Wrapped1& operator--() { --_value; return *this; } - + private: T _value; }; template - T true_value(Wrapped1 x) { return x.value(); } + T true_value(Wrapped1 x) { return x.value(); } template class Wrapped2 @@ -116,7 +115,7 @@ namespace { return _value < x._value; } convertible_to_bool operator==(const Wrapped2& x) const { return _value == x._value; } - + Wrapped2& operator+=(const Wrapped2& x) { _value += x._value; return *this; } Wrapped2& operator-=(const Wrapped2& x) @@ -139,7 +138,7 @@ namespace { _value >>= x._value; return *this; } Wrapped2& operator++() { ++_value; return *this; } Wrapped2& operator--() { --_value; return *this; } - + convertible_to_bool operator<(U u) const { return _value < u; } convertible_to_bool operator>(U u) const @@ -163,7 +162,7 @@ namespace }; template T true_value(Wrapped2 x) { return x.value(); } - + template class Wrapped3 : boost::equivalent > @@ -176,12 +175,12 @@ namespace convertible_to_bool operator<(const Wrapped3& x) const { return _value < x._value; } - + private: T _value; }; template - T true_value(Wrapped3 x) { return x.value(); } + T true_value(Wrapped3 x) { return x.value(); } template class Wrapped4 @@ -198,7 +197,7 @@ namespace convertible_to_bool operator<(const Wrapped4& x) const { return _value < x._value; } - + convertible_to_bool operator<(U u) const { return _value < u; } convertible_to_bool operator>(U u) const @@ -209,7 +208,7 @@ namespace }; template T true_value(Wrapped4 x) { return x.value(); } - + // U must be convertible to T template class Wrapped5 @@ -249,7 +248,7 @@ namespace }; template T true_value(Wrapped5 x) { return x.value(); } - + // U must be convertible to T template class Wrapped6 @@ -291,7 +290,7 @@ namespace }; template T true_value(Wrapped6 x) { return x.value(); } - + // MyInt uses only the single template-argument form of all_operators<> typedef Wrapped1 MyInt; @@ -320,7 +319,7 @@ namespace BOOST_TEST( static_cast(x1 >= y1) == static_cast(x2 >= y2) ); BOOST_TEST( static_cast(x1 > y1) == static_cast(x2 > y2) ); } - + template void test_less_than_comparable(X1 x1, Y1 y1, X2 x2, Y2 y2) { @@ -335,7 +334,7 @@ namespace BOOST_TEST( static_cast(x1 == y1) == static_cast(x2 == y2) ); BOOST_TEST( static_cast(x1 != y1) == static_cast(x2 != y2) ); } - + template void test_equality_comparable(X1 x1, Y1 y1, X2 x2, Y2 y2) { @@ -349,7 +348,7 @@ namespace { BOOST_TEST( (x1 * y1).value() == (x2 * y2) ); } - + template void test_multipliable(X1 x1, Y1 y1, X2 x2, Y2 y2) { @@ -358,21 +357,21 @@ namespace test_multipliable_aux( y1, x1, y2, x2 ); } - template - void test_value_equality(A a, B b) - { - BOOST_TEST(a.value() == b); - } - + template + void test_value_equality(A a, B b) + { + BOOST_TEST(a.value() == b); + } + #define TEST_OP_R(op) test_value_equality(x1 op y1, x2 op y2) #define TEST_OP_L(op) test_value_equality(y1 op x1, y2 op x2) - + template void test_addable_aux(X1 x1, Y1 y1, X2 x2, Y2 y2) { TEST_OP_R(+); } - + template void test_addable(X1 x1, Y1 y1, X2 x2, Y2 y2) { @@ -402,7 +401,7 @@ namespace if ( y2 != 0 ) TEST_OP_R(/); } - + template void test_dividable_left(X1 x1, Y1 y1, X2 x2, Y2 y2) { @@ -418,7 +417,7 @@ namespace if ( y2 != 0 ) TEST_OP_R(%); } - + template void test_modable_left(X1 x1, Y1 y1, X2 x2, Y2 y2) { @@ -432,7 +431,7 @@ namespace { TEST_OP_R(^); } - + template void test_xorable(X1 x1, Y1 y1, X2 x2, Y2 y2) { @@ -440,13 +439,13 @@ namespace test_xorable_aux( x1, y1, x2, y2 ); test_xorable_aux( y1, x1, y2, x2 ); } - + template void test_andable_aux(X1 x1, Y1 y1, X2 x2, Y2 y2) { TEST_OP_R(&); } - + template void test_andable(X1 x1, Y1 y1, X2 x2, Y2 y2) { @@ -454,13 +453,13 @@ namespace test_andable_aux( x1, y1, x2, y2 ); test_andable_aux( y1, x1, y2, x2 ); } - + template void test_orable_aux(X1 x1, Y1 y1, X2 x2, Y2 y2) { TEST_OP_R(|); } - + template void test_orable(X1 x1, Y1 y1, X2 x2, Y2 y2) { @@ -468,21 +467,21 @@ namespace test_orable_aux( x1, y1, x2, y2 ); test_orable_aux( y1, x1, y2, x2 ); } - + template void test_left_shiftable(X1 x1, Y1 y1, X2 x2, Y2 y2) { sanity_check( x1, y1, x2, y2 ); TEST_OP_R(<<); } - + template void test_right_shiftable(X1 x1, Y1 y1, X2 x2, Y2 y2) { sanity_check( x1, y1, x2, y2 ); TEST_OP_R(>>); } - + template void test_incrementable(X1 x1, X2 x2) { @@ -490,7 +489,7 @@ namespace BOOST_TEST( (x1++).value() == x2++ ); BOOST_TEST( x1.value() == x2 ); } - + template void test_decrementable(X1 x1, X2 x2) { @@ -498,7 +497,7 @@ namespace BOOST_TEST( (x1--).value() == x2-- ); BOOST_TEST( x1.value() == x2 ); } - + template void test_all(X1 x1, Y1 y1, X2 x2, Y2 y2) { @@ -517,7 +516,7 @@ namespace test_incrementable( x1, x2 ); test_decrementable( x1, x2 ); } - + template void test_left(X1 x1, Y1 y1, X2 x2, Y2 y2) { @@ -534,7 +533,7 @@ namespace Big b1 = Big( randomizer() ); Big b2 = Big( randomizer() ); Small s = Small( randomizer() ); - + test_all( Wrapped1(b1), Wrapped1(b2), b1, b2 ); test_all( Wrapped2(b1), s, b1, s ); } @@ -547,7 +546,7 @@ namespace { Big b1 = Big( randomizer() ); Small s = Small( randomizer() ); - + test_left( Wrapped6(b1), s, b1, s ); } }; @@ -612,9 +611,11 @@ main() Point x; x = x + Point(3, 4); x = x - Point(3, 4); - + cout << "Created point, and operated on it." << endl; - + +#if !defined(UBSAN) + // Using random values produce UB in various tests, such as shifting by more than the left operand capacity or signed integer overflows for (int n = 0; n < 1000; ++n) // was 10,000 but took too long (Beman) { boost::detail::minstd_rand r; @@ -623,7 +624,7 @@ main() tester()(r); tester()(r); tester()(r); - + tester()(r); tester()(r); tester()(r); @@ -638,8 +639,9 @@ main() tester_left()(r); tester_left()(r); } - + cout << "Did random tester loop." << endl; +#endif // !defined(UBSAN) MyInt i1(1); MyInt i2(2); @@ -691,7 +693,7 @@ main() cout << "Created MyLong objects.\n"; PRIVATE_EXPR_TEST( (j = j2), (j.value() == 2) ); - + BOOST_TEST( static_cast(j2 == j) ); BOOST_TEST( static_cast(2 == j) ); BOOST_TEST( static_cast(j2 == 2) ); @@ -721,41 +723,41 @@ main() BOOST_TEST( static_cast((j1 + 2) == 3) ); BOOST_TEST( static_cast((1 + j2) == 3) ); PRIVATE_EXPR_TEST( (j = j1 + j2), (j.value() == 3) ); - + BOOST_TEST( static_cast((j + 2) == 5) ); BOOST_TEST( static_cast((3 + j2) == 5) ); PRIVATE_EXPR_TEST( (j = j + j2), (j.value() == 5) ); - + BOOST_TEST( static_cast((j - 1) == 4) ); PRIVATE_EXPR_TEST( (j = j - j1), (j.value() == 4) ); - + BOOST_TEST( static_cast((j * 2) == 8) ); BOOST_TEST( static_cast((4 * j2) == 8) ); PRIVATE_EXPR_TEST( (j = j * j2), (j.value() == 8) ); - + BOOST_TEST( static_cast((j / 2) == 4) ); PRIVATE_EXPR_TEST( (j = j / j2), (j.value() == 4) ); - + BOOST_TEST( static_cast((j % 3) == 1) ); PRIVATE_EXPR_TEST( (j = j % ( j - j1 )), (j.value() == 1) ); - + PRIVATE_EXPR_TEST( (j = j2 + j2), (j.value() == 4) ); - + BOOST_TEST( static_cast((1 | j2 | j) == 7) ); BOOST_TEST( static_cast((j1 | 2 | j) == 7) ); BOOST_TEST( static_cast((j1 | j2 | 4) == 7) ); PRIVATE_EXPR_TEST( (j = j1 | j2 | j), (j.value() == 7) ); - + BOOST_TEST( static_cast((7 & j2) == 2) ); BOOST_TEST( static_cast((j & 2) == 2) ); PRIVATE_EXPR_TEST( (j = j & j2), (j.value() == 2) ); - + PRIVATE_EXPR_TEST( (j = j | j1), (j.value() == 3) ); - + BOOST_TEST( static_cast((3 ^ j1) == 2) ); BOOST_TEST( static_cast((j ^ 1) == 2) ); PRIVATE_EXPR_TEST( (j = j ^ j1), (j.value() == 2) ); - + PRIVATE_EXPR_TEST( (j = ( j + j1 ) * ( j2 | j1 )), (j.value() == 9) ); BOOST_TEST( static_cast((j1 << 2) == 4) ); @@ -765,7 +767,7 @@ main() BOOST_TEST( static_cast((j >> 2) == 1) ); BOOST_TEST( static_cast((j2 >> 1) == 1) ); PRIVATE_EXPR_TEST( (j = j2 >> j1), (j.value() == 1) ); - + cout << "Performed tests on MyLong objects.\n"; MyChar k1(1); @@ -788,7 +790,7 @@ main() BOOST_TEST( static_cast(k2 > k1) ); BOOST_TEST( static_cast(k2 >= k1) ); BOOST_TEST( static_cast(k2 >= k) ); - + cout << "Performed tests on MyChar objects.\n"; MyShort l1(1); @@ -802,7 +804,7 @@ main() cout << "Created MyShort objects.\n"; PRIVATE_EXPR_TEST( (l = l2), (l.value() == 2) ); - + BOOST_TEST( static_cast(l2 == l) ); BOOST_TEST( static_cast(2 == l) ); BOOST_TEST( static_cast(l2 == 2) ); @@ -828,9 +830,9 @@ main() BOOST_TEST( static_cast(l2 >= l) ); BOOST_TEST( static_cast(2 >= l) ); BOOST_TEST( static_cast(l2 >= 2) ); - + cout << "Performed tests on MyShort objects.\n"; - + MyDoubleInt di1(1); MyDoubleInt di2(2.); MyDoubleInt half(0.5); @@ -845,7 +847,7 @@ main() cout << "Created MyDoubleInt objects.\n"; PRIVATE_EXPR_TEST( (di = di2), (di.value() == 2) ); - + BOOST_TEST( static_cast(di2 == di) ); BOOST_TEST( static_cast(2 == di) ); BOOST_TEST( static_cast(di == 2) ); @@ -892,7 +894,7 @@ main() cout << "Created MyLongInt objects.\n"; PRIVATE_EXPR_TEST( (li = li2), (li.value() == 2) ); - + BOOST_TEST( static_cast(li2 == li) ); BOOST_TEST( static_cast(2 == li) ); BOOST_TEST( static_cast(li == 2) );