mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-09 03:15:11 +00:00
Bug 732875 - 1/8 - switch CheckedInt to support stdint types instead of PR int types - r=jwalden
This commit is contained in:
parent
b8fe19da4f
commit
f9040a6b65
@ -48,8 +48,11 @@ namespace mozilla {
|
||||
|
||||
namespace CheckedInt_internal {
|
||||
|
||||
/* we don't want to use std::numeric_limits here because PRInt... types may not support it,
|
||||
* depending on the platform, e.g. on certain platforms they use nonstandard built-in types
|
||||
/* historically, we didn't want to use std::numeric_limits here because PRInt... types may not support it,
|
||||
* depending on the platform, e.g. on certain platforms they use nonstandard built-in types.
|
||||
*
|
||||
* Maybe we should revisit this now that we use stdint types. But anyway, I don't think that std::numeric_limits
|
||||
* helps much with twice_bigger_type.
|
||||
*/
|
||||
|
||||
/*** Step 1: manually record information for all the types that we want to support
|
||||
@ -75,14 +78,14 @@ template<> struct integer_type_manually_recorded_info<T> \
|
||||
};
|
||||
|
||||
// Type Twice Bigger Type Unsigned Type
|
||||
CHECKEDINT_REGISTER_SUPPORTED_TYPE(PRInt8, PRInt16, PRUint8)
|
||||
CHECKEDINT_REGISTER_SUPPORTED_TYPE(PRUint8, PRUint16, PRUint8)
|
||||
CHECKEDINT_REGISTER_SUPPORTED_TYPE(PRInt16, PRInt32, PRUint16)
|
||||
CHECKEDINT_REGISTER_SUPPORTED_TYPE(PRUint16, PRUint32, PRUint16)
|
||||
CHECKEDINT_REGISTER_SUPPORTED_TYPE(PRInt32, PRInt64, PRUint32)
|
||||
CHECKEDINT_REGISTER_SUPPORTED_TYPE(PRUint32, PRUint64, PRUint32)
|
||||
CHECKEDINT_REGISTER_SUPPORTED_TYPE(PRInt64, unsupported_type, PRUint64)
|
||||
CHECKEDINT_REGISTER_SUPPORTED_TYPE(PRUint64, unsupported_type, PRUint64)
|
||||
CHECKEDINT_REGISTER_SUPPORTED_TYPE(int8_t, int16_t, uint8_t)
|
||||
CHECKEDINT_REGISTER_SUPPORTED_TYPE(uint8_t, uint16_t, uint8_t)
|
||||
CHECKEDINT_REGISTER_SUPPORTED_TYPE(int16_t, int32_t, uint16_t)
|
||||
CHECKEDINT_REGISTER_SUPPORTED_TYPE(uint16_t, uint32_t, uint16_t)
|
||||
CHECKEDINT_REGISTER_SUPPORTED_TYPE(int32_t, int64_t, uint32_t)
|
||||
CHECKEDINT_REGISTER_SUPPORTED_TYPE(uint32_t, uint64_t, uint32_t)
|
||||
CHECKEDINT_REGISTER_SUPPORTED_TYPE(int64_t, unsupported_type, uint64_t)
|
||||
CHECKEDINT_REGISTER_SUPPORTED_TYPE(uint64_t, unsupported_type, uint64_t)
|
||||
|
||||
|
||||
/*** Step 2: record some info about a given integer type,
|
||||
@ -312,8 +315,8 @@ inline T opposite_if_signed(T x) { return opposite_if_signed_impl<T>::run(x); }
|
||||
|
||||
/** \class CheckedInt
|
||||
* \brief Integer wrapper class checking for integer overflow and other errors
|
||||
* \param T the integer type to wrap. Can be any of PRInt8, PRUint8, PRInt16, PRUint16,
|
||||
* PRInt32, PRUint32, PRInt64, PRUint64.
|
||||
* \param T the integer type to wrap. Can be any of int8_t, uint8_t, int16_t, uint16_t,
|
||||
* int32_t, uint32_t, int64_t, uint64_t.
|
||||
*
|
||||
* This class implements guarded integer arithmetic. Do a computation, check that
|
||||
* valid() returns true, you then have a guarantee that no problem, such as integer overflow,
|
||||
@ -326,9 +329,9 @@ inline T opposite_if_signed(T x) { return opposite_if_signed_impl<T>::run(x); }
|
||||
* that doesn't crash if z==0, and that reports on error (divide by zero or integer overflow).
|
||||
* You could code it as follows:
|
||||
\code
|
||||
bool compute_x_plus_y_over_z(PRInt32 x, PRInt32 y, PRInt32 z, PRInt32 *result)
|
||||
bool compute_x_plus_y_over_z(int32_t x, int32_t y, int32_t z, int32_t *result)
|
||||
{
|
||||
CheckedInt<PRInt32> checked_result = (CheckedInt<PRInt32>(x) + y) / z;
|
||||
CheckedInt<int32_t> checked_result = (CheckedInt<int32_t>(x) + y) / z;
|
||||
*result = checked_result.value();
|
||||
return checked_result.valid();
|
||||
}
|
||||
@ -338,12 +341,12 @@ inline T opposite_if_signed(T x) { return opposite_if_signed_impl<T>::run(x); }
|
||||
* is checked to be in range before being casted to the destination type. This means that the following
|
||||
* lines all compile, and the resulting CheckedInts are correctly detected as valid or invalid:
|
||||
* \code
|
||||
CheckedInt<PRUint8> x(1); // 1 is of type int, is found to be in range for PRUint8, x is valid
|
||||
CheckedInt<PRUint8> x(-1); // -1 is of type int, is found not to be in range for PRUint8, x is invalid
|
||||
CheckedInt<PRInt8> x(-1); // -1 is of type int, is found to be in range for PRInt8, x is valid
|
||||
CheckedInt<PRInt8> x(PRInt16(1000)); // 1000 is of type PRInt16, is found not to be in range for PRInt8, x is invalid
|
||||
CheckedInt<PRInt32> x(PRUint32(3123456789)); // 3123456789 is of type PRUint32, is found not to be in range
|
||||
// for PRInt32, x is invalid
|
||||
CheckedInt<uint8_t> x(1); // 1 is of type int, is found to be in range for uint8_t, x is valid
|
||||
CheckedInt<uint8_t> x(-1); // -1 is of type int, is found not to be in range for uint8_t, x is invalid
|
||||
CheckedInt<int8_t> x(-1); // -1 is of type int, is found to be in range for int8_t, x is valid
|
||||
CheckedInt<int8_t> x(int16_t(1000)); // 1000 is of type int16_t, is found not to be in range for int8_t, x is invalid
|
||||
CheckedInt<int32_t> x(uint32_t(3123456789)); // 3123456789 is of type uint32_t, is found not to be in range
|
||||
// for int32_t, x is invalid
|
||||
* \endcode
|
||||
* Implicit conversion from
|
||||
* checked integers to plain integers is not allowed. As shown in the
|
||||
@ -356,8 +359,8 @@ inline T opposite_if_signed(T x) { return opposite_if_signed_impl<T>::run(x); }
|
||||
*
|
||||
* There are convenience typedefs for all PR integer types, of the following form (these are just 2 examples):
|
||||
\code
|
||||
typedef CheckedInt<PRInt32> CheckedInt32;
|
||||
typedef CheckedInt<PRUint16> CheckedUint16;
|
||||
typedef CheckedInt<int32_t> CheckedInt32;
|
||||
typedef CheckedInt<uint16_t> CheckedUint16;
|
||||
\endcode
|
||||
*/
|
||||
template<typename T>
|
||||
|
@ -428,14 +428,14 @@ void test()
|
||||
bool(is_signed) == false ? 0 : \
|
||||
sizeof(T) >= sizeof(U)); \
|
||||
}
|
||||
VERIFY_CONSTRUCTION_FROM_INTEGER_TYPE(PRInt8)
|
||||
VERIFY_CONSTRUCTION_FROM_INTEGER_TYPE(PRUint8)
|
||||
VERIFY_CONSTRUCTION_FROM_INTEGER_TYPE(PRInt16)
|
||||
VERIFY_CONSTRUCTION_FROM_INTEGER_TYPE(PRUint16)
|
||||
VERIFY_CONSTRUCTION_FROM_INTEGER_TYPE(PRInt32)
|
||||
VERIFY_CONSTRUCTION_FROM_INTEGER_TYPE(PRUint32)
|
||||
VERIFY_CONSTRUCTION_FROM_INTEGER_TYPE(PRInt64)
|
||||
VERIFY_CONSTRUCTION_FROM_INTEGER_TYPE(PRUint64)
|
||||
VERIFY_CONSTRUCTION_FROM_INTEGER_TYPE(int8_t)
|
||||
VERIFY_CONSTRUCTION_FROM_INTEGER_TYPE(uint8_t)
|
||||
VERIFY_CONSTRUCTION_FROM_INTEGER_TYPE(int16_t)
|
||||
VERIFY_CONSTRUCTION_FROM_INTEGER_TYPE(uint16_t)
|
||||
VERIFY_CONSTRUCTION_FROM_INTEGER_TYPE(int32_t)
|
||||
VERIFY_CONSTRUCTION_FROM_INTEGER_TYPE(uint32_t)
|
||||
VERIFY_CONSTRUCTION_FROM_INTEGER_TYPE(int64_t)
|
||||
VERIFY_CONSTRUCTION_FROM_INTEGER_TYPE(uint64_t)
|
||||
|
||||
/* Test increment/decrement operators */
|
||||
|
||||
@ -470,14 +470,14 @@ void test()
|
||||
|
||||
int main()
|
||||
{
|
||||
CheckedInt_test::test<PRInt8>();
|
||||
CheckedInt_test::test<PRUint8>();
|
||||
CheckedInt_test::test<PRInt16>();
|
||||
CheckedInt_test::test<PRUint16>();
|
||||
CheckedInt_test::test<PRInt32>();
|
||||
CheckedInt_test::test<PRUint32>();
|
||||
CheckedInt_test::test<PRInt64>();
|
||||
CheckedInt_test::test<PRUint64>();
|
||||
CheckedInt_test::test<int8_t>();
|
||||
CheckedInt_test::test<uint8_t>();
|
||||
CheckedInt_test::test<int16_t>();
|
||||
CheckedInt_test::test<uint16_t>();
|
||||
CheckedInt_test::test<int32_t>();
|
||||
CheckedInt_test::test<uint32_t>();
|
||||
CheckedInt_test::test<int64_t>();
|
||||
CheckedInt_test::test<uint64_t>();
|
||||
|
||||
std::cerr << CheckedInt_test::g_tests_failed << " tests failed, "
|
||||
<< CheckedInt_test::g_tests_passed << " tests passed out of "
|
||||
|
Loading…
Reference in New Issue
Block a user