1 /*! 2 * \file intsafe.h 3 * 4 * \brief Windows helper functions for integer overflow prevention 5 * 6 * \package This file is part of the ReactOS PSDK package. 7 * 8 * \author 9 * Timo Kreuzer (timo.kreuzer@reactos.org) 10 * 11 * \copyright THIS SOFTWARE IS NOT COPYRIGHTED 12 * 13 * This source code is offered for use in the public domain. You may 14 * use, modify or distribute it freely. 15 * 16 * This code is distributed in the hope that it will be useful but 17 * WITHOUT ANY WARRANTY. ALL WARRANTIES, EXPRESS OR IMPLIED ARE HEREBY 18 * DISCLAIMED. This includes but is not limited to warranties of 19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 20 * 21 * \todo 22 * - missing conversion functions 23 * - multiplication functions 24 * - signed add, sub and multiply functions 25 */ 26 #pragma once 27 28 #ifndef _INTSAFE_H_INCLUDED_ 29 #define _INTSAFE_H_INCLUDED_ 30 31 #include <specstrings.h> 32 33 /* Handle ntintsafe here too */ 34 #ifdef _NTINTSAFE_H_INCLUDED_ 35 #ifndef _NTDEF_ /* Guard agains redefinition from ntstatus.h */ 36 typedef _Return_type_success_(return >= 0) long NTSTATUS; 37 #endif 38 #define NT_SUCCESS(Status) (((NTSTATUS)(Status)) >= 0) 39 #define STATUS_SUCCESS ((NTSTATUS)0x00000000) 40 #define STATUS_INTEGER_OVERFLOW ((NTSTATUS)0xC0000095) 41 #define INTSAFE_RESULT NTSTATUS 42 #define INTSAFE_SUCCESS STATUS_SUCCESS 43 #define INTSAFE_E_ARITHMETIC_OVERFLOW STATUS_INTEGER_OVERFLOW 44 #define INTSAFE_NAME(name) Rtl##name 45 #else // _NTINTSAFE_H_INCLUDED_ 46 #ifndef _HRESULT_DEFINED 47 typedef _Return_type_success_(return >= 0) long HRESULT; 48 #endif 49 #define SUCCEEDED(hr) (((HRESULT)(hr)) >= 0) 50 #define FAILED(hr) (((HRESULT)(hr)) < 0) 51 #define S_OK ((HRESULT)0L) 52 #define INTSAFE_RESULT HRESULT 53 #define INTSAFE_SUCCESS S_OK 54 #define INTSAFE_E_ARITHMETIC_OVERFLOW ((HRESULT)0x80070216L) 55 #define INTSAFE_NAME(name) name 56 #endif // _NTINTSAFE_H_INCLUDED_ 57 58 #if !defined(_W64) 59 #if defined(_MSC_VER) && !defined(__midl) && (defined(_M_IX86) || defined(_M_ARM)) 60 #define _W64 __w64 61 #else 62 #define _W64 63 #endif 64 #endif 65 66 /* Static assert */ 67 #ifndef C_ASSERT 68 #ifdef _MSC_VER 69 # define C_ASSERT(e) typedef char __C_ASSERT__[(e)?1:-1] 70 #else 71 # define C_ASSERT(e) extern void __C_ASSERT__(int [(e)?1:-1]) 72 #endif 73 #endif /* C_ASSERT */ 74 75 /* Typedefs */ 76 #ifndef _WINNT_ 77 #ifndef _NTDEF_ 78 typedef char CHAR; 79 typedef unsigned char UCHAR, UINT8; 80 typedef signed char INT8; 81 typedef short SHORT; 82 typedef signed short INT16; 83 typedef unsigned short USHORT, UINT16; 84 typedef int INT; 85 typedef unsigned int UINT32; 86 typedef signed int INT32; 87 typedef long LONG; 88 typedef unsigned long ULONG; 89 typedef long long LONGLONG, LONG64; 90 typedef signed long long INT64; 91 typedef unsigned long long ULONGLONG, DWORDLONG, ULONG64, DWORD64, UINT64; 92 #ifdef _WIN64 93 typedef long long INT_PTR, LONG_PTR, SSIZE_T, ptrdiff_t; 94 typedef unsigned long long UINT_PTR, ULONG_PTR, DWORD_PTR, SIZE_T, size_t; 95 #else // _WIN64 96 typedef _W64 int INT_PTR, ptrdiff_t; 97 typedef _W64 unsigned int UINT_PTR, size_t; 98 typedef _W64 long LONG_PTR, SSIZE_T; 99 typedef _W64 unsigned long ULONG_PTR, DWORD_PTR, SIZE_T; 100 #endif // _WIN64 101 #endif 102 typedef unsigned char BYTE; 103 typedef unsigned short WORD; 104 typedef unsigned int UINT; 105 typedef unsigned long DWORD; 106 #endif // _WINNT_ 107 108 /* Just to be sure! */ 109 C_ASSERT(sizeof(USHORT) == 2); 110 C_ASSERT(sizeof(INT) == 4); 111 C_ASSERT(sizeof(UINT) == 4); 112 C_ASSERT(sizeof(LONG) == 4); 113 C_ASSERT(sizeof(ULONG) == 4); 114 C_ASSERT(sizeof(DWORD) == 4); 115 C_ASSERT(sizeof(UINT_PTR) == sizeof(ULONG_PTR)); 116 117 /* Integer range margins (use (x-1) to prevent warnings) */ 118 #define INT8_MIN ((signed char)(-127 - 1)) 119 #define SHORT_MIN (-32768) 120 #define INT16_MIN ((short)(-32767 - 1)) 121 #define INT_MIN (-2147483647 - 1) 122 #define INT32_MIN (-2147483647 - 1) 123 #define LONG_MIN (-2147483647L - 1) 124 #define LONGLONG_MIN (-9223372036854775807LL - 1) 125 #define LONG64_MIN (-9223372036854775807LL - 1) 126 #define INT64_MIN (-9223372036854775807LL - 1) 127 #define INT128_MIN (-170141183460469231731687303715884105727i128 - 1) 128 #ifdef _WIN64 129 #define INT_PTR_MIN (-9223372036854775807LL - 1) 130 #define LONG_PTR_MIN (-9223372036854775807LL - 1) 131 #define PTRDIFF_T_MIN (-9223372036854775807LL - 1) 132 #define SSIZE_T_MIN (-9223372036854775807LL - 1) 133 #else /* _WIN64 */ 134 #define INT_PTR_MIN (-2147483647 - 1) 135 #define LONG_PTR_MIN (-2147483647L - 1) 136 #define PTRDIFF_T_MIN (-2147483647 - 1) 137 #define SSIZE_T_MIN (-2147483647L - 1) 138 #endif /* _WIN64 */ 139 140 #define INT8_MAX ((signed char)127) 141 #define UINT8_MAX ((unsigned char)0xffU) 142 #define BYTE_MAX ((unsigned char)0xff) 143 #define SHORT_MAX ((short)32767) 144 #define INT16_MAX ((short)32767) 145 #define USHORT_MAX ((unsigned short)0xffff) 146 #define UINT16_MAX ((unsigned short)0xffff) 147 #define WORD_MAX ((unsigned short)0xffff) 148 #define INT_MAX 2147483647 149 #define INT32_MAX 2147483647 150 #define UINT_MAX 0xffffffff 151 #define UINT32_MAX 0xffffffffU 152 #define LONG_MAX 2147483647L 153 #define ULONG_MAX 0xffffffffUL 154 #define DWORD_MAX 0xffffffffUL 155 #define LONGLONG_MAX 9223372036854775807LL 156 #define LONG64_MAX 9223372036854775807LL 157 #define INT64_MAX 9223372036854775807LL 158 #define ULONGLONG_MAX 0xffffffffffffffffULL 159 #define DWORDLONG_MAX 0xffffffffffffffffULL 160 #define ULONG64_MAX 0xffffffffffffffffULL 161 #define DWORD64_MAX 0xffffffffffffffffULL 162 #define UINT64_MAX 0xffffffffffffffffULL 163 #define INT128_MAX 170141183460469231731687303715884105727i128 164 #define UINT128_MAX 0xffffffffffffffffffffffffffffffffui128 165 #undef SIZE_T_MAX 166 #ifdef _WIN64 167 #define INT_PTR_MAX 9223372036854775807LL 168 #define UINT_PTR_MAX 0xffffffffffffffffULL 169 #define LONG_PTR_MAX 9223372036854775807LL 170 #define ULONG_PTR_MAX 0xffffffffffffffffULL 171 #define DWORD_PTR_MAX 0xffffffffffffffffULL 172 #define PTRDIFF_T_MAX 9223372036854775807LL 173 #define SIZE_T_MAX 0xffffffffffffffffULL 174 #define SSIZE_T_MAX 9223372036854775807LL 175 #define _SIZE_T_MAX 0xffffffffffffffffULL 176 #else /* _WIN64 */ 177 #define INT_PTR_MAX 2147483647 178 #define UINT_PTR_MAX 0xffffffff 179 #define LONG_PTR_MAX 2147483647L 180 #define ULONG_PTR_MAX 0xffffffffUL 181 #define DWORD_PTR_MAX 0xffffffffUL 182 #define PTRDIFF_T_MAX 2147483647 183 #define SIZE_T_MAX 0xffffffff 184 #define SSIZE_T_MAX 2147483647L 185 #define _SIZE_T_MAX 0xffffffffUL 186 #endif /* _WIN64 */ 187 188 /* Error values */ 189 #define INT8_ERROR ((signed char)(-1)) 190 #define UINT8_ERROR ((unsigned char)0xff) 191 #define BYTE_ERROR ((unsigned char)0xff) 192 #define SHORT_ERROR ((short)(-1)) 193 #define INT16_ERROR ((short)(-1)) 194 #define USHORT_ERROR ((unsigned short)0xffff) 195 #define UINT16_ERROR ((unsigned short)0xffff) 196 #define WORD_ERROR ((unsigned short)0xffff) 197 #define INT_ERROR (-1) 198 #define INT32_ERROR (-1) 199 #define UINT_ERROR 0xffffffffU 200 #define UINT32_ERROR 0xffffffffU 201 #define LONG_ERROR (-1L) 202 #define ULONG_ERROR 0xffffffffUL 203 #define DWORD_ERROR 0xffffffffUL 204 #define LONGLONG_ERROR (-1LL) 205 #define LONG64_ERROR (-1LL) 206 #define INT64_ERROR (-1LL) 207 #define ULONGLONG_ERROR 0xffffffffffffffffULL 208 #define DWORDLONG_ERROR 0xffffffffffffffffULL 209 #define ULONG64_ERROR 0xffffffffffffffffULL 210 #define UINT64_ERROR 0xffffffffffffffffULL 211 #ifdef _WIN64 212 #define INT_PTR_ERROR (-1LL) 213 #define UINT_PTR_ERROR 0xffffffffffffffffULL 214 #define LONG_PTR_ERROR (-1LL) 215 #define ULONG_PTR_ERROR 0xffffffffffffffffULL 216 #define DWORD_PTR_ERROR 0xffffffffffffffffULL 217 #define PTRDIFF_T_ERROR (-1LL) 218 #define SIZE_T_ERROR 0xffffffffffffffffULL 219 #define SSIZE_T_ERROR (-1LL) 220 #define _SIZE_T_ERROR 0xffffffffffffffffULL 221 #else /* _WIN64 */ 222 #define INT_PTR_ERROR (-1) 223 #define UINT_PTR_ERROR 0xffffffffU 224 #define LONG_PTR_ERROR (-1L) 225 #define ULONG_PTR_ERROR 0xffffffffUL 226 #define DWORD_PTR_ERROR 0xffffffffUL 227 #define PTRDIFF_T_ERROR (-1) 228 #define SIZE_T_ERROR 0xffffffffU 229 #define SSIZE_T_ERROR (-1L) 230 #define _SIZE_T_ERROR 0xffffffffUL 231 #endif /* _WIN64 */ 232 233 /* special definitons (the CHAR ones should not be defined here!) */ 234 #define _INTSAFE_CHAR CHAR 235 #define _INTSAFE_CHAR_ERROR ((signed char)(-1)) 236 #ifdef _CHAR_UNSIGNED 237 #define _INTSAFE_CHAR_MIN ((unsigned char)0) 238 #define _INTSAFE_CHAR_MAX ((unsigned char)0xff) 239 #else 240 #define _INTSAFE_CHAR_MIN ((signed char)(-128)) 241 #define _INTSAFE_CHAR_MAX ((signed char)127) 242 #endif /* _CHAR_UNSIGNED */ 243 244 #define size_t_ERROR SIZE_T_ERROR 245 #define UCHAR_ERROR '\0' 246 #define CHAR_ERROR '\0' 247 248 /* 32 bit x 32 bit to 64 bit unsigned multiplication */ 249 #ifndef UInt32x32To64 250 #define UInt32x32To64(a,b) ((unsigned __int64)(unsigned int)(a)*(unsigned __int64)(unsigned int)(b)) 251 #endif 252 253 /* Convert unsigned to signed or unsigned */ 254 #define DEFINE_SAFE_CONVERT_UTOX(_Name, _TypeFrom, _TypeTo) \ 255 _Must_inspect_result_ \ 256 __forceinline \ 257 INTSAFE_RESULT \ 258 INTSAFE_NAME(_Name)( \ 259 _In_ _TypeFrom Input, \ 260 _Out_ _Deref_out_range_(==, Input) _TypeTo *pOutput) \ 261 { \ 262 if ((sizeof(_TypeFrom) < sizeof(_TypeTo)) || (Input <= _TypeTo ## _MAX)) \ 263 { \ 264 *pOutput = (_TypeTo)Input; \ 265 return INTSAFE_SUCCESS; \ 266 } \ 267 else \ 268 { \ 269 *pOutput = _TypeTo ## _ERROR; \ 270 return INTSAFE_E_ARITHMETIC_OVERFLOW; \ 271 } \ 272 } 273 274 DEFINE_SAFE_CONVERT_UTOX(ByteToChar, BYTE, _INTSAFE_CHAR) 275 DEFINE_SAFE_CONVERT_UTOX(ByteToInt8, BYTE, INT8) 276 DEFINE_SAFE_CONVERT_UTOX(UInt8ToChar, UINT8, _INTSAFE_CHAR) 277 DEFINE_SAFE_CONVERT_UTOX(UInt8ToInt8, UINT8, INT8) 278 DEFINE_SAFE_CONVERT_UTOX(UShortToChar, USHORT, _INTSAFE_CHAR) 279 DEFINE_SAFE_CONVERT_UTOX(UShortToUChar, USHORT, UINT8) 280 DEFINE_SAFE_CONVERT_UTOX(UShortToInt8, USHORT, INT8) 281 DEFINE_SAFE_CONVERT_UTOX(UShortToUInt8, USHORT, UINT8) 282 DEFINE_SAFE_CONVERT_UTOX(UShortToShort, USHORT, SHORT) 283 DEFINE_SAFE_CONVERT_UTOX(UIntToUChar, UINT, UINT8) 284 DEFINE_SAFE_CONVERT_UTOX(UIntToInt8, UINT, INT8) 285 DEFINE_SAFE_CONVERT_UTOX(UIntToUInt8, UINT, UINT8) 286 DEFINE_SAFE_CONVERT_UTOX(UIntToShort, UINT, SHORT) 287 DEFINE_SAFE_CONVERT_UTOX(UIntToUShort, UINT, USHORT) 288 DEFINE_SAFE_CONVERT_UTOX(UIntToInt, UINT, INT) 289 DEFINE_SAFE_CONVERT_UTOX(UIntToLong, UINT, LONG) 290 DEFINE_SAFE_CONVERT_UTOX(UIntPtrToUChar, UINT_PTR, UINT8) 291 DEFINE_SAFE_CONVERT_UTOX(UIntPtrToInt8, UINT_PTR, INT8) 292 DEFINE_SAFE_CONVERT_UTOX(UIntPtrToUInt8, UINT_PTR, UINT8) 293 DEFINE_SAFE_CONVERT_UTOX(UIntPtrToShort, UINT_PTR, SHORT) 294 DEFINE_SAFE_CONVERT_UTOX(UIntPtrToUShort, UINT_PTR, USHORT) 295 DEFINE_SAFE_CONVERT_UTOX(UIntPtrToInt16, UINT_PTR, INT16) 296 DEFINE_SAFE_CONVERT_UTOX(UIntPtrToUInt16, UINT_PTR, UINT16) 297 DEFINE_SAFE_CONVERT_UTOX(UIntPtrToInt, UINT_PTR, INT) 298 DEFINE_SAFE_CONVERT_UTOX(UIntPtrToLong, UINT_PTR, LONG) 299 DEFINE_SAFE_CONVERT_UTOX(UIntPtrToIntPtr, UINT_PTR, INT_PTR) 300 DEFINE_SAFE_CONVERT_UTOX(UIntPtrToLongPtr, UINT_PTR, LONG_PTR) 301 DEFINE_SAFE_CONVERT_UTOX(ULongToUChar, ULONG, UINT8) 302 DEFINE_SAFE_CONVERT_UTOX(ULongToUInt8, ULONG, UINT8) 303 DEFINE_SAFE_CONVERT_UTOX(ULongToShort, ULONG, SHORT) 304 DEFINE_SAFE_CONVERT_UTOX(ULongToUShort, ULONG, USHORT) 305 DEFINE_SAFE_CONVERT_UTOX(ULongToInt, ULONG, INT) 306 DEFINE_SAFE_CONVERT_UTOX(ULongToUInt, ULONG, UINT) 307 DEFINE_SAFE_CONVERT_UTOX(ULongToIntPtr, ULONG, INT_PTR) 308 DEFINE_SAFE_CONVERT_UTOX(ULongToUIntPtr, ULONG, UINT_PTR) 309 DEFINE_SAFE_CONVERT_UTOX(ULongToLongPtr, ULONG, LONG_PTR) 310 DEFINE_SAFE_CONVERT_UTOX(ULongPtrToULong, ULONG_PTR, ULONG) 311 DEFINE_SAFE_CONVERT_UTOX(ULongLongToUInt, ULONGLONG, UINT) 312 DEFINE_SAFE_CONVERT_UTOX(ULongLongToULong, ULONGLONG, ULONG) 313 DEFINE_SAFE_CONVERT_UTOX(ULongLongToULongPtr, ULONGLONG, ULONG_PTR) 314 315 316 /* Convert signed to unsigned */ 317 #define DEFINE_SAFE_CONVERT_STOU(_Name, _TypeFrom, _TypeTo) \ 318 _Must_inspect_result_ \ 319 __forceinline \ 320 INTSAFE_RESULT \ 321 INTSAFE_NAME(_Name)( \ 322 _In_ _TypeFrom Input, \ 323 _Out_ _Deref_out_range_(==, Input) _TypeTo *pOutput) \ 324 { \ 325 if ((Input >= 0) && \ 326 ((sizeof(_TypeFrom) <= sizeof(_TypeTo)) || (Input <= (_TypeFrom)_TypeTo ## _MAX))) \ 327 { \ 328 *pOutput = (_TypeTo)Input; \ 329 return INTSAFE_SUCCESS; \ 330 } \ 331 else \ 332 { \ 333 *pOutput = _TypeTo ## _ERROR; \ 334 return INTSAFE_E_ARITHMETIC_OVERFLOW; \ 335 } \ 336 } 337 338 DEFINE_SAFE_CONVERT_STOU(Int8ToUChar, INT8, UINT8) 339 DEFINE_SAFE_CONVERT_STOU(Int8ToUInt8, INT8, UINT8) 340 DEFINE_SAFE_CONVERT_STOU(Int8ToUShort, INT8, USHORT) 341 DEFINE_SAFE_CONVERT_STOU(Int8ToUInt, INT8, UINT) 342 DEFINE_SAFE_CONVERT_STOU(Int8ToULong, INT8, ULONG) 343 DEFINE_SAFE_CONVERT_STOU(Int8ToUIntPtr, INT8, UINT_PTR) 344 DEFINE_SAFE_CONVERT_STOU(Int8ToULongPtr, INT8, ULONG_PTR) 345 DEFINE_SAFE_CONVERT_STOU(Int8ToULongLong, INT8, ULONGLONG) 346 DEFINE_SAFE_CONVERT_STOU(ShortToUChar, SHORT, UINT8) 347 DEFINE_SAFE_CONVERT_STOU(ShortToUInt8, SHORT, UINT8) 348 DEFINE_SAFE_CONVERT_STOU(ShortToUShort, SHORT, USHORT) 349 DEFINE_SAFE_CONVERT_STOU(ShortToUInt, SHORT, UINT) 350 DEFINE_SAFE_CONVERT_STOU(ShortToULong, SHORT, ULONG) 351 DEFINE_SAFE_CONVERT_STOU(ShortToUIntPtr, SHORT, UINT_PTR) 352 DEFINE_SAFE_CONVERT_STOU(ShortToULongPtr, SHORT, ULONG_PTR) 353 DEFINE_SAFE_CONVERT_STOU(ShortToDWordPtr, SHORT, DWORD_PTR) 354 DEFINE_SAFE_CONVERT_STOU(ShortToULongLong, SHORT, ULONGLONG) 355 DEFINE_SAFE_CONVERT_STOU(IntToUChar, INT, UINT8) 356 DEFINE_SAFE_CONVERT_STOU(IntToUInt8, INT, UINT8) 357 DEFINE_SAFE_CONVERT_STOU(IntToUShort, INT, USHORT) 358 DEFINE_SAFE_CONVERT_STOU(IntToUInt, INT, UINT) 359 DEFINE_SAFE_CONVERT_STOU(IntToULong, INT, ULONG) 360 DEFINE_SAFE_CONVERT_STOU(IntToULongLong, INT, ULONGLONG) 361 DEFINE_SAFE_CONVERT_STOU(LongToUChar, LONG, UINT8) 362 DEFINE_SAFE_CONVERT_STOU(LongToUInt8, LONG, UINT8) 363 DEFINE_SAFE_CONVERT_STOU(LongToUShort, LONG, USHORT) 364 DEFINE_SAFE_CONVERT_STOU(LongToUInt, LONG, UINT) 365 DEFINE_SAFE_CONVERT_STOU(LongToULong, LONG, ULONG) 366 DEFINE_SAFE_CONVERT_STOU(LongToUIntPtr, LONG, UINT_PTR) 367 DEFINE_SAFE_CONVERT_STOU(LongToULongPtr, LONG, ULONG_PTR) 368 DEFINE_SAFE_CONVERT_STOU(LongToULongLong, LONG, ULONGLONG) 369 DEFINE_SAFE_CONVERT_STOU(IntPtrToUChar, INT_PTR, UINT8) 370 DEFINE_SAFE_CONVERT_STOU(IntPtrToUInt8, INT_PTR, UINT8) 371 DEFINE_SAFE_CONVERT_STOU(IntPtrToUShort, INT_PTR, USHORT) 372 DEFINE_SAFE_CONVERT_STOU(IntPtrToUInt, INT_PTR, UINT) 373 DEFINE_SAFE_CONVERT_STOU(IntPtrToULong, INT_PTR, ULONG) 374 DEFINE_SAFE_CONVERT_STOU(IntPtrToUIntPtr, INT_PTR, UINT_PTR) 375 DEFINE_SAFE_CONVERT_STOU(IntPtrToULongPtr, INT_PTR, ULONG_PTR) 376 DEFINE_SAFE_CONVERT_STOU(IntPtrToULongLong, INT_PTR, ULONGLONG) 377 DEFINE_SAFE_CONVERT_STOU(LongPtrToUChar, LONG_PTR, UINT8) 378 DEFINE_SAFE_CONVERT_STOU(LongPtrToUInt8, LONG_PTR, UINT8) 379 DEFINE_SAFE_CONVERT_STOU(LongPtrToUShort, LONG_PTR, USHORT) 380 DEFINE_SAFE_CONVERT_STOU(LongPtrToUInt, LONG_PTR, UINT) 381 DEFINE_SAFE_CONVERT_STOU(LongPtrToULong, LONG_PTR, ULONG) 382 DEFINE_SAFE_CONVERT_STOU(LongPtrToUIntPtr, LONG_PTR, UINT_PTR) 383 DEFINE_SAFE_CONVERT_STOU(LongPtrToULongPtr, LONG_PTR, ULONG_PTR) 384 DEFINE_SAFE_CONVERT_STOU(LongPtrToULongLong, LONG_PTR, ULONGLONG) 385 DEFINE_SAFE_CONVERT_STOU(LongLongToULong, LONGLONG, ULONG) 386 DEFINE_SAFE_CONVERT_STOU(LongLongToULongPtr, LONGLONG, ULONG_PTR) 387 #ifdef _CHAR_UNSIGNED 388 DEFINE_SAFE_CONVERT_STOU(ShortToChar, SHORT, UINT8) 389 DEFINE_SAFE_CONVERT_STOU(LongPtrToChar, LONG_PTR, UINT8) 390 #endif 391 392 393 /* Convert signed to signed */ 394 #define DEFINE_SAFE_CONVERT_STOS(_Name, _TypeFrom, _TypeTo) \ 395 _Must_inspect_result_ \ 396 __forceinline \ 397 INTSAFE_RESULT \ 398 INTSAFE_NAME(_Name)( \ 399 _In_ _TypeFrom Input, \ 400 _Out_ _Deref_out_range_(==, Input) _TypeTo *pOutput) \ 401 { \ 402 if ((Input >= _TypeTo ## _MIN) && (Input <= _TypeTo ## _MAX)) \ 403 { \ 404 *pOutput = (_TypeTo)Input; \ 405 return INTSAFE_SUCCESS; \ 406 } \ 407 else \ 408 { \ 409 *pOutput = _TypeTo ## _ERROR; \ 410 return INTSAFE_E_ARITHMETIC_OVERFLOW; \ 411 } \ 412 } 413 414 DEFINE_SAFE_CONVERT_STOS(ShortToInt8, SHORT, INT8) 415 DEFINE_SAFE_CONVERT_STOS(IntToInt8, INT, INT8) 416 DEFINE_SAFE_CONVERT_STOS(IntToShort, INT, SHORT) 417 DEFINE_SAFE_CONVERT_STOS(LongToInt8, LONG, INT8) 418 DEFINE_SAFE_CONVERT_STOS(LongToShort, LONG, SHORT) 419 DEFINE_SAFE_CONVERT_STOS(LongToInt, LONG, INT) 420 DEFINE_SAFE_CONVERT_STOS(IntPtrToInt8, INT_PTR, INT8) 421 DEFINE_SAFE_CONVERT_STOS(IntPtrToShort, INT_PTR, SHORT) 422 DEFINE_SAFE_CONVERT_STOS(IntPtrToInt, INT_PTR, INT) 423 DEFINE_SAFE_CONVERT_STOS(IntPtrToLong, INT_PTR, LONG) 424 DEFINE_SAFE_CONVERT_STOS(IntPtrToLongPtr, INT_PTR, LONG_PTR) 425 DEFINE_SAFE_CONVERT_STOS(LongPtrToInt8, LONG_PTR, INT8) 426 DEFINE_SAFE_CONVERT_STOS(LongPtrToShort, LONG_PTR, SHORT) 427 DEFINE_SAFE_CONVERT_STOS(LongPtrToInt, LONG_PTR, INT) 428 DEFINE_SAFE_CONVERT_STOS(LongPtrToLong, LONG_PTR, LONG) 429 DEFINE_SAFE_CONVERT_STOS(LongPtrToIntPtr, LONG_PTR, INT_PTR) 430 DEFINE_SAFE_CONVERT_STOS(LongLongToInt, LONGLONG, INT) 431 DEFINE_SAFE_CONVERT_STOS(LongLongToLong, LONGLONG, LONG) 432 DEFINE_SAFE_CONVERT_STOS(LongLongToIntPtr, LONGLONG, INT_PTR) 433 DEFINE_SAFE_CONVERT_STOS(LongLongToLongPtr, LONGLONG, LONG_PTR) 434 DEFINE_SAFE_CONVERT_STOS(ShortToChar, SHORT, _INTSAFE_CHAR) 435 DEFINE_SAFE_CONVERT_STOS(LongPtrToChar, LONG_PTR, _INTSAFE_CHAR) 436 437 438 #ifdef _NTINTSAFE_H_INCLUDED_ 439 440 #define RtlInt8ToByte RtlInt8ToUInt8 441 #define RtlInt8ToUInt16 RtlInt8ToUShort 442 #define RtlInt8ToWord RtlInt8ToUShort 443 #define RtlInt8ToUInt32 RtlInt8ToUInt 444 #define RtlInt8ToDWord RtlInt8ToULong 445 #define RtlInt8ToDWordPtr RtlInt8ToULongPtr 446 #define RtlInt8ToDWordLong RtlInt8ToULongLong 447 #define RtlInt8ToULong64 RtlInt8ToULongLong 448 #define RtlInt8ToDWord64 RtlInt8ToULongLong 449 #define RtlInt8ToUInt64 RtlInt8ToULongLong 450 #define RtlInt8ToSizeT RtlInt8ToUIntPtr 451 #define RtlInt8ToSIZET RtlInt8ToULongPtr 452 #define RtlIntToSizeT RtlIntToUIntPtr 453 #define RtlIntToSIZET RtlIntToULongPtr 454 #define RtlULongToSSIZET RtlULongToLongPtr 455 #define RtlULongToByte RtlULongToUInt8 456 #define RtlULongLongToInt64 RtlULongLongToLongLong 457 #define RtlULongLongToLong64 RtlULongLongToLongLong 458 #define RtlULongLongToPtrdiffT RtlULongLongToIntPtr 459 #define RtlULongLongToSizeT RtlULongLongToUIntPtr 460 #define RtlULongLongToSSIZET RtlULongLongToLongPtr 461 #define RtlULongLongToSIZET RtlULongLongToULongPtr 462 #define RtlSIZETToULong RtlULongPtrToULong 463 #define RtlSSIZETToULongLong RtlLongPtrToULongLong 464 #define RtlSSIZETToULong RtlLongPtrToULong 465 #define RtlLongLongToSizeT RtlLongLongToUIntPtr 466 #define RtlLongLongToSSIZET RtlLongLongToLongPtr 467 #define RtlLongLongToSIZET RtlLongLongToULongPtr 468 #ifdef _WIN64 469 #define RtlIntToUIntPtr RtlIntToULongLong 470 #define RtlULongLongToIntPtr RtlULongLongToLongLong 471 #else 472 #define RtlIntToUIntPtr RtlIntToUInt 473 #define RtlULongLongToIntPtr RtlULongLongToInt 474 #define RtlULongLongToUIntPtr RtlULongLongToUInt 475 #define RtlULongLongToULongPtr RtlULongLongToULong 476 #endif 477 478 #else // _NTINTSAFE_H_INCLUDED_ 479 480 #define Int8ToByte Int8ToUInt8 481 #define Int8ToUInt16 Int8ToUShort 482 #define Int8ToWord Int8ToUShort 483 #define Int8ToUInt32 Int8ToUInt 484 #define Int8ToDWord Int8ToULong 485 #define Int8ToDWordPtr Int8ToULongPtr 486 #define Int8ToDWordLong Int8ToULongLong 487 #define Int8ToULong64 Int8ToULongLong 488 #define Int8ToDWord64 Int8ToULongLong 489 #define Int8ToUInt64 Int8ToULongLong 490 #define Int8ToSizeT Int8ToUIntPtr 491 #define Int8ToSIZET Int8ToULongPtr 492 #define IntToSizeT IntToUIntPtr 493 #define IntToSIZET IntToULongPtr 494 #define ULongToSSIZET ULongToLongPtr 495 #define ULongToByte ULongToUInt8 496 #define ULongLongToInt64 ULongLongToLongLong 497 #define ULongLongToLong64 ULongLongToLongLong 498 #define ULongLongToPtrdiffT ULongLongToIntPtr 499 #define ULongLongToSizeT ULongLongToUIntPtr 500 #define ULongLongToSSIZET ULongLongToLongPtr 501 #define ULongLongToSIZET ULongLongToULongPtr 502 #define SIZETToULong ULongPtrToULong 503 #define SSIZETToULongLong LongPtrToULongLong 504 #define SSIZETToULong LongPtrToULong 505 #define LongLongToSizeT LongLongToUIntPtr 506 #define LongLongToSSIZET LongLongToLongPtr 507 #define LongLongToSIZET LongLongToULongPtr 508 #ifdef _WIN64 509 #define IntToUIntPtr IntToULongLong 510 #define ULongLongToIntPtr ULongLongToLongLong 511 #else 512 #define IntToUIntPtr IntToUInt 513 #define ULongLongToIntPtr ULongLongToInt 514 #define ULongLongToUIntPtr ULongLongToUInt 515 #define ULongLongToULongPtr ULongLongToULong 516 #endif 517 518 #endif // _NTINTSAFE_H_INCLUDED_ 519 520 521 #define DEFINE_SAFE_ADD(_Name, _Type) \ 522 _Must_inspect_result_ \ 523 __forceinline \ 524 INTSAFE_RESULT \ 525 INTSAFE_NAME(_Name)( \ 526 _In_ _Type Augend, \ 527 _In_ _Type Addend, \ 528 _Out_ _Deref_out_range_(==, Augend + Addend) _Type *pOutput) \ 529 { \ 530 if ((_Type)(Augend + Addend) >= Augend) \ 531 { \ 532 *pOutput = Augend + Addend; \ 533 return INTSAFE_SUCCESS; \ 534 } \ 535 else \ 536 { \ 537 *pOutput = _Type ## _ERROR; \ 538 return INTSAFE_E_ARITHMETIC_OVERFLOW; \ 539 } \ 540 } 541 542 DEFINE_SAFE_ADD(UInt8Add, UINT8) 543 DEFINE_SAFE_ADD(UShortAdd, USHORT) 544 DEFINE_SAFE_ADD(UIntAdd, UINT) 545 DEFINE_SAFE_ADD(ULongAdd, ULONG) 546 DEFINE_SAFE_ADD(UIntPtrAdd, UINT_PTR) 547 DEFINE_SAFE_ADD(ULongPtrAdd, ULONG_PTR) 548 DEFINE_SAFE_ADD(DWordPtrAdd, DWORD_PTR) 549 DEFINE_SAFE_ADD(SizeTAdd, size_t) 550 DEFINE_SAFE_ADD(SIZETAdd, SIZE_T) 551 DEFINE_SAFE_ADD(ULongLongAdd, ULONGLONG) 552 553 554 #define DEFINE_SAFE_SUB(_Name, _Type) \ 555 _Must_inspect_result_ \ 556 __forceinline \ 557 INTSAFE_RESULT \ 558 INTSAFE_NAME(_Name)( \ 559 _In_ _Type Minuend, \ 560 _In_ _Type Subtrahend, \ 561 _Out_ _Deref_out_range_(==, Minuend - Subtrahend) _Type* pOutput) \ 562 { \ 563 if (Minuend >= Subtrahend) \ 564 { \ 565 *pOutput = Minuend - Subtrahend; \ 566 return INTSAFE_SUCCESS; \ 567 } \ 568 else \ 569 { \ 570 *pOutput = _Type ## _ERROR; \ 571 return INTSAFE_E_ARITHMETIC_OVERFLOW; \ 572 } \ 573 } 574 575 DEFINE_SAFE_SUB(UInt8Sub, UINT8) 576 DEFINE_SAFE_SUB(UShortSub, USHORT) 577 DEFINE_SAFE_SUB(UIntSub, UINT) 578 DEFINE_SAFE_SUB(UIntPtrSub, UINT_PTR) 579 DEFINE_SAFE_SUB(ULongSub, ULONG) 580 DEFINE_SAFE_SUB(ULongPtrSub, ULONG_PTR) 581 DEFINE_SAFE_SUB(DWordPtrSub, DWORD_PTR) 582 DEFINE_SAFE_SUB(SizeTSub, size_t) 583 DEFINE_SAFE_SUB(SIZETSub, SIZE_T) 584 DEFINE_SAFE_SUB(ULongLongSub, ULONGLONG) 585 586 #ifdef ENABLE_INTSAFE_SIGNED_FUNCTIONS 587 _Must_inspect_result_ 588 __forceinline 589 INTSAFE_RESULT 590 INTSAFE_NAME(LongLongAdd)( 591 _In_ LONGLONG Augend, 592 _In_ LONGLONG Addend, 593 _Out_ _Deref_out_range_(==, Augend + Addend) LONGLONG* pResult) 594 { 595 LONGLONG Result = Augend + Addend; 596 597 /* The only way the result can overflow, is when the sign of the augend 598 and the addend are the same. In that case the result is expected to 599 have the same sign as the two, otherwise it overflowed. 600 Sign equality is checked with a binary xor operation. */ 601 if ( ((Augend ^ Addend) >= 0) && ((Augend ^ Result) < 0) ) 602 { 603 *pResult = LONGLONG_ERROR; 604 return INTSAFE_E_ARITHMETIC_OVERFLOW; 605 } 606 else 607 { 608 *pResult = Result; 609 return INTSAFE_SUCCESS; 610 } 611 } 612 613 614 #define DEFINE_SAFE_ADD_S(_Name, _Type1, _Type2, _Convert) \ 615 C_ASSERT(sizeof(_Type2) > sizeof(_Type1)); \ 616 _Must_inspect_result_ \ 617 __forceinline \ 618 INTSAFE_RESULT \ 619 INTSAFE_NAME(_Name)( \ 620 _In_ _Type1 Augend, \ 621 _In_ _Type1 Addend, \ 622 _Out_ _Deref_out_range_(==, Augend + Addend) _Type1* pOutput) \ 623 { \ 624 return INTSAFE_NAME(_Convert)(((_Type2)Augend) + ((_Type2)Addend), pOutput); \ 625 } 626 627 DEFINE_SAFE_ADD_S(Int8Add, INT8, SHORT, ShortToInt8) 628 DEFINE_SAFE_ADD_S(ShortAdd, SHORT, INT, IntToShort) 629 DEFINE_SAFE_ADD_S(IntAdd, INT, LONGLONG, LongLongToInt) 630 DEFINE_SAFE_ADD_S(LongAdd, LONG, LONGLONG, LongLongToLong) 631 #ifndef _WIN64 632 DEFINE_SAFE_ADD_S(IntPtrAdd, INT_PTR, LONGLONG, LongLongToIntPtr) 633 DEFINE_SAFE_ADD_S(LongPtrAdd, LONG_PTR, LONGLONG, LongLongToLongPtr) 634 #endif 635 636 _Must_inspect_result_ 637 __forceinline 638 INTSAFE_RESULT 639 INTSAFE_NAME(LongLongSub)( 640 _In_ LONGLONG Minuend, 641 _In_ LONGLONG Subtrahend, 642 _Out_ _Deref_out_range_(==, Minuend - Subtrahend) LONGLONG* pResult) 643 { 644 LONGLONG Result = Minuend - Subtrahend; 645 646 /* The only way the result can overflow, is when the sign of the minuend 647 and the subtrahend differ. In that case the result is expected to 648 have the same sign as the minuend, otherwise it overflowed. 649 Sign equality is checked with a binary xor operation. */ 650 if ( ((Minuend ^ Subtrahend) < 0) && ((Minuend ^ Result) < 0) ) 651 { 652 *pResult = LONGLONG_ERROR; 653 return INTSAFE_E_ARITHMETIC_OVERFLOW; 654 } 655 else 656 { 657 *pResult = Result; 658 return INTSAFE_SUCCESS; 659 } 660 } 661 662 663 #define DEFINE_SAFE_SUB_S(_Name, _Type1, _Type2, _Convert) \ 664 C_ASSERT(sizeof(_Type2) > sizeof(_Type1)); \ 665 _Must_inspect_result_ \ 666 __forceinline \ 667 INTSAFE_RESULT \ 668 INTSAFE_NAME(_Name)( \ 669 _In_ _Type1 Minuend, \ 670 _In_ _Type1 Subtrahend, \ 671 _Out_ _Deref_out_range_(==, Minuend - Subtrahend) _Type1* pOutput) \ 672 { \ 673 return INTSAFE_NAME(_Convert)(((_Type2)Minuend) - ((_Type2)Subtrahend), pOutput); \ 674 } 675 676 DEFINE_SAFE_SUB_S(LongSub, LONG, LONGLONG, LongLongToLong) 677 #ifndef _WIN64 678 DEFINE_SAFE_SUB_S(IntPtrSub, INT_PTR, LONGLONG, LongLongToIntPtr) 679 DEFINE_SAFE_SUB_S(LongPtrSub, LONG_PTR, LONGLONG, LongLongToLongPtr) 680 #endif 681 682 #endif /* ENABLE_INTSAFE_SIGNED_FUNCTIONS */ 683 684 _Must_inspect_result_ 685 __forceinline 686 INTSAFE_RESULT 687 INTSAFE_NAME(ULongLongMult)( 688 _In_ ULONGLONG Multiplicand, 689 _In_ ULONGLONG Multiplier, 690 _Out_ _Deref_out_range_(==, Multiplicand * Multiplier) ULONGLONG* pOutput) 691 { 692 /* We can split the 64 bit numbers in low and high parts: 693 M1 = M1Low + M1Hi * 0x100000000 694 M2 = M2Low + M2Hi * 0x100000000 695 696 Then the multiplication looks like this: 697 M1 * M2 = (M1Low + M1Hi * 0x100000000) * (M2Low + M2Hi * 0x100000000) 698 = M1Low * M2Low 699 + M1Low * M2Hi * 0x100000000 700 + M2Low * M1Hi * 0x100000000 701 + M1Hi * M2Hi * 0x100000000 * 0x100000000 702 703 We get an overflow when 704 a) M1Hi * M2Hi != 0, so when M1Hi and M2Hi are both not 0 705 b) The product of the nonzero high part and the other low part 706 is larger than 32 bits. 707 c) The addition of the product from b) shifted left by 32 and 708 M1Low * M2Low is larger than 64 bits 709 */ 710 ULONG M1Low = Multiplicand & 0xffffffff; 711 ULONG M2Low = Multiplier & 0xffffffff; 712 ULONG M1Hi = Multiplicand >> 32; 713 ULONG M2Hi = Multiplier >> 32; 714 ULONGLONG Temp; 715 716 if (M1Hi == 0) 717 { 718 Temp = UInt32x32To64(M1Low, M2Hi); 719 } 720 else if (M2Hi == 0) 721 { 722 Temp = UInt32x32To64(M1Hi, M2Low); 723 } 724 else 725 { 726 *pOutput = ULONGLONG_ERROR; 727 return INTSAFE_E_ARITHMETIC_OVERFLOW; 728 } 729 730 if (Temp > ULONG_MAX) 731 { 732 *pOutput = ULONGLONG_ERROR; 733 return INTSAFE_E_ARITHMETIC_OVERFLOW; 734 } 735 736 return INTSAFE_NAME(ULongLongAdd)(Temp << 32, UInt32x32To64(M1Low, M2Low), pOutput); 737 } 738 739 740 #define DEFINE_SAFE_MULT_U32(_Name, _Type, _Convert) \ 741 _Must_inspect_result_ \ 742 __forceinline \ 743 INTSAFE_RESULT \ 744 INTSAFE_NAME(_Name)( \ 745 _In_ _Type Multiplicand, \ 746 _In_ _Type Multiplier, \ 747 _Out_ _Deref_out_range_(==, Multiplicand * Multiplier) _Type* pOutput) \ 748 { \ 749 ULONGLONG Result = UInt32x32To64(Multiplicand, Multiplier); \ 750 return INTSAFE_NAME(_Convert)(Result, pOutput); \ 751 } 752 753 DEFINE_SAFE_MULT_U32(ULongMult, ULONG, ULongLongToULong) 754 #ifndef _WIN64 755 DEFINE_SAFE_MULT_U32(SizeTMult, size_t, ULongLongToSizeT) 756 DEFINE_SAFE_MULT_U32(SIZETMult, SIZE_T, ULongLongToSIZET) 757 #endif 758 759 #define DEFINE_SAFE_MULT_U16(_Name, _Type, _Convert) \ 760 _Must_inspect_result_ \ 761 __forceinline \ 762 INTSAFE_RESULT \ 763 INTSAFE_NAME(_Name)( \ 764 _In_ _Type Multiplicand, \ 765 _In_ _Type Multiplier, \ 766 _Out_ _Deref_out_range_(==, Multiplicand * Multiplier) _Type* pOutput) \ 767 { \ 768 ULONG Result = ((ULONG)Multiplicand) * ((ULONG)Multiplier); \ 769 return INTSAFE_NAME(_Convert)(Result, pOutput); \ 770 } 771 772 DEFINE_SAFE_MULT_U16(UShortMult, USHORT, ULongToUShort) 773 774 775 #ifdef _NTINTSAFE_H_INCLUDED_ 776 777 #define RtlUInt16Add RtlUShortAdd 778 #define RtlWordAdd RtlUShortAdd 779 #define RtlUInt32Add RtlUIntAdd 780 #define RtlDWordAdd RtlULongAdd 781 #define RtlDWordLongAdd RtlULongLongAdd 782 #define RtlULong64Add RtlULongLongAdd 783 #define RtlDWord64Add RtlULongLongAdd 784 #define RtlUInt64Add RtlULongLongAdd 785 #define RtlUInt16Sub RtlUShortSub 786 #define RtlWordSub RtlUShortSub 787 #define RtlUInt32Sub RtlUIntSub 788 #define RtlDWordSub RtlULongSub 789 #define RtlDWordLongSub RtlULongLongSub 790 #define RtlULong64Sub RtlULongLongSub 791 #define RtlDWord64Sub RtlULongLongSub 792 #define RtlUInt64Sub RtlULongLongSub 793 #define RtlUInt16Mult RtlUShortMult 794 #define RtlWordMult RtlUShortMult 795 #ifdef _WIN64 796 #define RtlIntPtrAdd RtlLongLongAdd 797 #define RtlLongPtrAdd RtlLongLongAdd 798 #define RtlIntPtrSub RtlLongLongSub 799 #define RtlLongPtrSub RtlLongLongSub 800 #define RtlSizeTMult RtlULongLongMult 801 #define RtlSIZETMult RtlULongLongMult 802 #else 803 #endif 804 805 #else // _NTINTSAFE_H_INCLUDED_ 806 807 #define UInt16Add UShortAdd 808 #define WordAdd UShortAdd 809 #define UInt32Add UIntAdd 810 #define DWordAdd ULongAdd 811 #define DWordLongAdd ULongLongAdd 812 #define ULong64Add ULongLongAdd 813 #define DWord64Add ULongLongAdd 814 #define UInt64Add ULongLongAdd 815 #define UInt16Sub UShortSub 816 #define WordSub UShortSub 817 #define UInt32Sub UIntSub 818 #define DWordSub ULongSub 819 #define DWordLongSub ULongLongSub 820 #define ULong64Sub ULongLongSub 821 #define DWord64Sub ULongLongSub 822 #define UInt64Sub ULongLongSub 823 #define UInt16Mult UShortMult 824 #define WordMult UShortMult 825 #ifdef _WIN64 826 #define IntPtrAdd LongLongAdd 827 #define LongPtrAdd LongLongAdd 828 #define IntPtrSub LongLongSub 829 #define LongPtrSub LongLongSub 830 #define SizeTMult ULongLongMult 831 #define SIZETMult ULongLongMult 832 #else 833 #endif 834 835 #undef _INTSAFE_CHAR_MIN 836 #undef _INTSAFE_CHAR_MAX 837 #undef _INTSAFE_CHAR_ERROR 838 839 #endif // _NTINTSAFE_H_INCLUDED_ 840 841 #endif // !_INTSAFE_H_INCLUDED_ 842