177 lines
3.6 KiB
C++
177 lines
3.6 KiB
C++
// 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;
|
|
}
|
|
|
|
} |