[PSDK]
authorThomas Faber <thomas.faber@reactos.org>
Sun, 26 Jul 2015 08:03:02 +0000 (08:03 +0000)
committerThomas Faber <thomas.faber@reactos.org>
Sun, 26 Jul 2015 08:03:02 +0000 (08:03 +0000)
- Add support for intsafe signed Add functions
- Guard signed math in ENABLE_INTSAFE_SIGNED_FUNCTIONS
CORE-9947 #resolve

svn path=/trunk/; revision=68573

reactos/include/psdk/intsafe.h
rostests/kmtests/rtl/RtlIntSafe.c

index db8a6e6..e30cb11 100644 (file)
@@ -433,6 +433,7 @@ DEFINE_SAFE_CONVERT_STOS(LongPtrToShort, LONG_PTR, SHORT)
 DEFINE_SAFE_CONVERT_STOS(LongPtrToInt, LONG_PTR, INT)
 DEFINE_SAFE_CONVERT_STOS(LongPtrToLong, LONG_PTR, LONG)
 DEFINE_SAFE_CONVERT_STOS(LongPtrToIntPtr, LONG_PTR, INT_PTR)
+DEFINE_SAFE_CONVERT_STOS(LongLongToInt, LONGLONG, INT)
 DEFINE_SAFE_CONVERT_STOS(LongLongToLong, LONGLONG, LONG)
 DEFINE_SAFE_CONVERT_STOS(LongLongToIntPtr, LONGLONG, INT_PTR)
 DEFINE_SAFE_CONVERT_STOS(LongLongToLongPtr, LONGLONG, LONG_PTR)
@@ -582,6 +583,55 @@ DEFINE_SAFE_SUB(SizeTSub, size_t)
 DEFINE_SAFE_SUB(SIZETSub, SIZE_T)
 DEFINE_SAFE_SUB(ULongLongSub, ULONGLONG)
 
+#ifdef ENABLE_INTSAFE_SIGNED_FUNCTIONS
+_Must_inspect_result_
+__forceinline
+INTSAFE_RESULT
+INTSAFE_NAME(LongLongAdd)(
+    _In_ LONGLONG Augend,
+    _In_ LONGLONG Addend,
+    _Out_ _Deref_out_range_(==, Augend + Addend) LONGLONG* pResult)
+{
+    LONGLONG Result = Augend + Addend;
+
+    /* The only way the result can overflow, is when the sign of the augend
+       and the addend are the same. In that case the result is expected to
+       have the same sign as the two, otherwise it overflowed.
+       Sign equality is checked with a binary xor operation. */
+    if ( ((Augend ^ Addend) >= 0) && ((Augend ^ Result) < 0) )
+    {
+        *pResult = LONGLONG_ERROR;
+        return INTSAFE_E_ARITHMETIC_OVERFLOW;
+    }
+    else
+    {
+        *pResult = Result;
+        return INTSAFE_SUCCESS;
+    }
+}
+
+
+#define DEFINE_SAFE_ADD_S(_Name, _Type1, _Type2, _Convert) \
+C_ASSERT(sizeof(_Type2) > sizeof(_Type1)); \
+_Must_inspect_result_ \
+__forceinline \
+INTSAFE_RESULT \
+INTSAFE_NAME(_Name)( \
+    _In_ _Type1 Augend, \
+    _In_ _Type1 Addend, \
+    _Out_ _Deref_out_range_(==, Augend + Addend) _Type1* pOutput) \
+{ \
+    return INTSAFE_NAME(_Convert)(((_Type2)Augend) + ((_Type2)Addend), pOutput); \
+}
+
+DEFINE_SAFE_ADD_S(Int8Add, INT8, SHORT, ShortToInt8)
+DEFINE_SAFE_ADD_S(ShortAdd, SHORT, INT, IntToShort)
+DEFINE_SAFE_ADD_S(IntAdd, INT, LONGLONG, LongLongToInt)
+DEFINE_SAFE_ADD_S(LongAdd, LONG, LONGLONG, LongLongToLong)
+#ifndef _WIN64
+DEFINE_SAFE_ADD_S(IntPtrAdd, INT_PTR, LONGLONG, LongLongToIntPtr)
+DEFINE_SAFE_ADD_S(LongPtrAdd, LONG_PTR, LONGLONG, LongLongToLongPtr)
+#endif
 
 _Must_inspect_result_
 __forceinline
@@ -611,6 +661,7 @@ INTSAFE_NAME(LongLongSub)(
 
 
 #define DEFINE_SAFE_SUB_S(_Name, _Type1, _Type2, _Convert) \
+C_ASSERT(sizeof(_Type2) > sizeof(_Type1)); \
 _Must_inspect_result_ \
 __forceinline \
 INTSAFE_RESULT \
@@ -628,6 +679,7 @@ DEFINE_SAFE_SUB_S(IntPtrSub, INT_PTR, LONGLONG, LongLongToIntPtr)
 DEFINE_SAFE_SUB_S(LongPtrSub, LONG_PTR, LONGLONG, LongLongToLongPtr)
 #endif
 
+#endif /* ENABLE_INTSAFE_SIGNED_FUNCTIONS */
 
 _Must_inspect_result_
 __forceinline
@@ -741,6 +793,8 @@ DEFINE_SAFE_MULT_U16(UShortMult, USHORT, ULongToUShort)
 #define RtlUInt16Mult RtlUShortMult
 #define RtlWordMult RtlUShortMult
 #ifdef _WIN64
+#define RtlIntPtrAdd RtlLongLongAdd
+#define RtlLongPtrAdd RtlLongLongAdd
 #define RtlIntPtrSub RtlLongLongSub
 #define RtlLongPtrSub RtlLongLongSub
 #define RtlSizeTMult RtlULongLongMult
@@ -769,6 +823,8 @@ DEFINE_SAFE_MULT_U16(UShortMult, USHORT, ULongToUShort)
 #define UInt16Mult UShortMult
 #define WordMult UShortMult
 #ifdef _WIN64
+#define IntPtrAdd LongLongAdd
+#define LongPtrAdd LongLongAdd
 #define IntPtrSub LongLongSub
 #define LongPtrSub LongLongSub
 #define SizeTMult ULongLongMult
index 0a9632d..1e59b87 100644 (file)
@@ -111,4 +111,36 @@ START_TEST(RtlIntSafe)
     TEST_ADD(UInt8,     UINT8,      uint,       UINT8_MAX - 1,      1,              UINT8_MAX,      STATUS_SUCCESS);
     TEST_ADD(UInt8,     UINT8,      uint,       UINT8_MAX,          1,              (UINT8)-1,      STATUS_INTEGER_OVERFLOW);
     TEST_ADD(UInt8,     UINT8,      uint,       UINT8_MAX,          UINT8_MAX,      (UINT8)-1,      STATUS_INTEGER_OVERFLOW);
+
+    TEST_ADD(Int8,      INT8,       int,        0,                  0,              0,              STATUS_SUCCESS);
+    TEST_ADD(Int8,      INT8,       int,        5,                  5,              10,             STATUS_SUCCESS);
+    TEST_ADD(Int8,      INT8,       int,        0,                  INT8_MAX,       INT8_MAX,       STATUS_SUCCESS);
+    TEST_ADD(Int8,      INT8,       int,        INT8_MAX,           0,              INT8_MAX,       STATUS_SUCCESS);
+    TEST_ADD(Int8,      INT8,       int,        INT8_MAX - 1,       1,              INT8_MAX,       STATUS_SUCCESS);
+    TEST_ADD(Int8,      INT8,       int,        INT8_MAX,           1,              (INT8)-1,       STATUS_INTEGER_OVERFLOW);
+    TEST_ADD(Int8,      INT8,       int,        INT8_MAX,           INT8_MAX,       (INT8)-1,       STATUS_INTEGER_OVERFLOW);
+    TEST_ADD(Int8,      INT8,       int,        0,                  -1,             -1,             STATUS_SUCCESS);
+    TEST_ADD(Int8,      INT8,       int,        -1,                 0,              -1,             STATUS_SUCCESS);
+    TEST_ADD(Int8,      INT8,       int,        0,                  INT8_MIN,       INT8_MIN,       STATUS_SUCCESS);
+    TEST_ADD(Int8,      INT8,       int,        INT8_MIN,           0,              INT8_MIN,       STATUS_SUCCESS);
+    TEST_ADD(Int8,      INT8,       int,        INT8_MAX,           INT8_MIN,       (INT8)-1,       STATUS_SUCCESS);
+    TEST_ADD(Int8,      INT8,       int,        INT8_MIN,           -1,             (INT8)-1,       STATUS_INTEGER_OVERFLOW);
+    TEST_ADD(Int8,      INT8,       int,        INT8_MIN,           INT8_MIN,       (INT8)-1,       STATUS_INTEGER_OVERFLOW);
+
+    TEST_ADD(LongLong,  LONGLONG,   longlong,   0,                  0,              0,              STATUS_SUCCESS);
+    TEST_ADD(LongLong,  LONGLONG,   longlong,   5,                  5,              10,             STATUS_SUCCESS);
+    TEST_ADD(LongLong,  LONGLONG,   longlong,   0,                  LONGLONG_MAX,   LONGLONG_MAX,   STATUS_SUCCESS);
+    TEST_ADD(LongLong,  LONGLONG,   longlong,   LONGLONG_MAX,       0,              LONGLONG_MAX,   STATUS_SUCCESS);
+    TEST_ADD(LongLong,  LONGLONG,   longlong,   LONGLONG_MAX - 1,   1,              LONGLONG_MAX,   STATUS_SUCCESS);
+    TEST_ADD(LongLong,  LONGLONG,   longlong,   LONGLONG_MAX,       1,              (LONGLONG)-1,   STATUS_INTEGER_OVERFLOW);
+    TEST_ADD(LongLong,  LONGLONG,   longlong,   LONGLONG_MAX,       INT8_MAX,       (LONGLONG)-1,   STATUS_INTEGER_OVERFLOW);
+    TEST_ADD(LongLong,  LONGLONG,   longlong,   0,                  -1,             -1,             STATUS_SUCCESS);
+    TEST_ADD(LongLong,  LONGLONG,   longlong,   -1,                 0,              -1,             STATUS_SUCCESS);
+    TEST_ADD(LongLong,  LONGLONG,   longlong,   0,                  LONGLONG_MIN,   LONGLONG_MIN,   STATUS_SUCCESS);
+    TEST_ADD(LongLong,  LONGLONG,   longlong,   LONGLONG_MIN,       0,              LONGLONG_MIN,   STATUS_SUCCESS);
+    TEST_ADD(LongLong,  LONGLONG,   longlong,   LONGLONG_MAX,       LONGLONG_MIN,   (LONGLONG)-1,   STATUS_SUCCESS);
+    TEST_ADD(LongLong,  LONGLONG,   longlong,   LONGLONG_MIN,       -1,             (LONGLONG)-1,   STATUS_INTEGER_OVERFLOW);
+    TEST_ADD(LongLong,  LONGLONG,   longlong,   LONGLONG_MIN,       LONGLONG_MIN,   (LONGLONG)-1,   STATUS_INTEGER_OVERFLOW);
+    TEST_ADD(LongLong,  LONGLONG,   longlong,   ULONG_MAX,          1,              0x100000000LL,  STATUS_SUCCESS);
+    TEST_ADD(LongLong,  LONGLONG,   longlong,   ULONG_MAX,          ULONG_MAX,      0x1fffffffeLL,  STATUS_SUCCESS);
 }