| // Copyright (c) OWASP Project (https://www.owasp.org), 2011. All rights reserved. | |
| // Licensed under the MIT License. | |
| #include "TestMain.h" | |
| #include "TestCase.h" | |
| #if defined(__GNUC__) | |
| # include <stdint.h> | |
| #endif | |
| #if !defined(CHAR_BIT) | |
| # include <limits.h> | |
| #endif | |
| namespace mod_verify | |
| { | |
| template <typename T> | |
| std::string type_name() | |
| { | |
| std::ostringstream ostm; | |
| ostm << (std::numeric_limits<T>::is_signed ? "int" : "uint"); | |
| ostm << (sizeof(T) == 1 ? 8 : sizeof(T) * 8); | |
| return ostm.str(); | |
| } | |
| // ModVerifyTest2 tests (x) % (0). | |
| template<typename T> | |
| struct ModVerifyTest1 | |
| { | |
| ModVerifyTest1<T>() | |
| { | |
| const size_t width = sizeof(T); | |
| const size_t shift = width * CHAR_BIT - 1; | |
| const bool expected = true; | |
| bool divzero; | |
| SafeInt<T> x = (T)((std::uint64_t)1 << shift); | |
| SafeInt<T> m(0); | |
| /////////////////////////////////////////////// | |
| try | |
| { | |
| T r; | |
| r = x % m; | |
| divzero = false; | |
| } | |
| catch(SafeIntException&) | |
| { | |
| divzero = true; | |
| } | |
| if(divzero != expected) | |
| { | |
| std::cerr << "Error in case " << type_name<T>() << ": "; | |
| std::cerr << to_hex((T)x) << ", " << to_hex((T)m) << ", "; | |
| std::cerr << "expected = " << (expected ? "divzero" : "no divzero") << std::endl; | |
| } | |
| /////////////////////////////////////////////// | |
| try | |
| { | |
| T r = x; | |
| r %= m; | |
| divzero = false; | |
| } | |
| catch(SafeIntException&) | |
| { | |
| divzero = true; | |
| } | |
| if(divzero != expected) | |
| { | |
| std::cerr << "Error in case " << type_name<T>() << ": "; | |
| std::cerr << to_hex((T)x) << ", " << to_hex((T)m) << ", "; | |
| std::cerr << "expected = " << (expected ? "divzero" : "no divzero") << std::endl; | |
| } | |
| } | |
| }; | |
| // ModVerifyTest2 tests (INT_MIN) % (-1). | |
| template<typename T> | |
| struct ModVerifyTest2 | |
| { | |
| ModVerifyTest2<T>() | |
| { | |
| const size_t width = sizeof(T); | |
| const size_t shift = width * CHAR_BIT - 1; | |
| // GCC using a native built-in int will raise SIGFPE or | |
| // #DE. However, according to LeBlanc, SafeInt's contract | |
| // is to return the correct mathematical result or throw. | |
| // const bool expected = (s == Signed ? true : false); | |
| const bool expected = false; | |
| bool overflow; | |
| SafeInt<T> x = (T)((std::uint64_t)1 << shift); | |
| SafeInt<T> m((T)-1); | |
| /////////////////////////////////////////////// | |
| try | |
| { | |
| T r; | |
| r = x % m; | |
| overflow = false; | |
| } | |
| catch(SafeIntException&) | |
| { | |
| overflow = true; | |
| } | |
| if(overflow != expected) | |
| { | |
| std::cerr << "Error in case " << type_name<T>() << ": "; | |
| std::cerr << to_hex((T)x) << ", " << to_hex((T)m) << ", "; | |
| std::cerr << "expected = " << (expected ? "overflow" : "no overflow") << std::endl; | |
| } | |
| /////////////////////////////////////////////// | |
| try | |
| { | |
| T r = x; | |
| r %= m; | |
| overflow = false; | |
| } | |
| catch(SafeIntException&) | |
| { | |
| overflow = true; | |
| } | |
| if(overflow != expected) | |
| { | |
| std::cerr << "Error in case " << type_name<T>() << ": "; | |
| std::cerr << to_hex((T)x) << ", " << to_hex((T)m) << ", "; | |
| std::cerr << "expected = " << (expected ? "overflow" : "no overflow") << std::endl; | |
| } | |
| } | |
| }; | |
| void ModVerify() | |
| { | |
| std::cout << "Verifying Reduction:" << std::endl; | |
| ModVerifyTest1<std::uint64_t> t11; | |
| ModVerifyTest1<std::int64_t> t12; | |
| ModVerifyTest1<std::uint32_t> t13; | |
| ModVerifyTest1<std::int32_t> t14; | |
| ModVerifyTest1<std::uint16_t> t15; | |
| ModVerifyTest1<std::int16_t> t16; | |
| ModVerifyTest1<std::uint8_t> t17; | |
| ModVerifyTest1<std::int8_t> t18; | |
| ModVerifyTest2<std::uint64_t> t21; | |
| ModVerifyTest2<std::int64_t> t22; | |
| ModVerifyTest2<std::uint32_t> t23; | |
| ModVerifyTest2<std::int32_t> t24; | |
| ModVerifyTest2<std::uint16_t> t25; | |
| ModVerifyTest2<std::int16_t> t26; | |
| ModVerifyTest2<std::uint8_t> t27; | |
| ModVerifyTest2<std::int8_t> t28; | |
| // Lets see..... | |
| ModVerifyTest1<size_t> t50; | |
| ModVerifyTest2<size_t> t51; | |
| } | |
| } |