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 (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 #ifdef _CHAR_UNSIGNED 386 DEFINE_SAFE_CONVERT_STOU(ShortToChar, SHORT, UINT8) 387 DEFINE_SAFE_CONVERT_STOU(LongPtrToChar, LONG_PTR, UINT8) 388 #endif 389 390 391 /* Convert signed to signed */ 392 #define DEFINE_SAFE_CONVERT_STOS(_Name, _TypeFrom, _TypeTo) \ 393 _Must_inspect_result_ \ 394 __forceinline \ 395 INTSAFE_RESULT \ 396 INTSAFE_NAME(_Name)( \ 397 _In_ _TypeFrom Input, \ 398 _Out_ _Deref_out_range_(==, Input) _TypeTo *pOutput) \ 399 { \ 400 if ((Input >= _TypeTo ## _MIN) && (Input <= _TypeTo ## _MAX)) \ 401 { \ 402 *pOutput = (_TypeTo)Input; \ 403 return INTSAFE_SUCCESS; \ 404 } \ 405 else \ 406 { \ 407 *pOutput = _TypeTo ## _ERROR; \ 408 return INTSAFE_E_ARITHMETIC_OVERFLOW; \ 409 } \ 410 } 411 412 DEFINE_SAFE_CONVERT_STOS(ShortToInt8, SHORT, INT8) 413 DEFINE_SAFE_CONVERT_STOS(IntToInt8, INT, INT8) 414 DEFINE_SAFE_CONVERT_STOS(IntToShort, INT, SHORT) 415 DEFINE_SAFE_CONVERT_STOS(LongToInt8, LONG, INT8) 416 DEFINE_SAFE_CONVERT_STOS(LongToShort, LONG, SHORT) 417 DEFINE_SAFE_CONVERT_STOS(LongToInt, LONG, INT) 418 DEFINE_SAFE_CONVERT_STOS(IntPtrToInt8, INT_PTR, INT8) 419 DEFINE_SAFE_CONVERT_STOS(IntPtrToShort, INT_PTR, SHORT) 420 DEFINE_SAFE_CONVERT_STOS(IntPtrToInt, INT_PTR, INT) 421 DEFINE_SAFE_CONVERT_STOS(IntPtrToLong, INT_PTR, LONG) 422 DEFINE_SAFE_CONVERT_STOS(IntPtrToLongPtr, INT_PTR, LONG_PTR) 423 DEFINE_SAFE_CONVERT_STOS(LongPtrToInt8, LONG_PTR, INT8) 424 DEFINE_SAFE_CONVERT_STOS(LongPtrToShort, LONG_PTR, SHORT) 425 DEFINE_SAFE_CONVERT_STOS(LongPtrToInt, LONG_PTR, INT) 426 DEFINE_SAFE_CONVERT_STOS(LongPtrToLong, LONG_PTR, LONG) 427 DEFINE_SAFE_CONVERT_STOS(LongPtrToIntPtr, LONG_PTR, INT_PTR) 428 DEFINE_SAFE_CONVERT_STOS(LongLongToInt, LONGLONG, INT) 429 DEFINE_SAFE_CONVERT_STOS(LongLongToLong, LONGLONG, LONG) 430 DEFINE_SAFE_CONVERT_STOS(LongLongToIntPtr, LONGLONG, INT_PTR) 431 DEFINE_SAFE_CONVERT_STOS(LongLongToLongPtr, LONGLONG, LONG_PTR) 432 DEFINE_SAFE_CONVERT_STOS(ShortToChar, SHORT, _INTSAFE_CHAR) 433 DEFINE_SAFE_CONVERT_STOS(LongPtrToChar, LONG_PTR, _INTSAFE_CHAR) 434 435 436 #ifdef _NTINTSAFE_H_INCLUDED_ 437 438 #define RtlInt8ToByte RtlInt8ToUInt8 439 #define RtlInt8ToUInt16 RtlInt8ToUShort 440 #define RtlInt8ToWord RtlInt8ToUShort 441 #define RtlInt8ToUInt32 RtlInt8ToUInt 442 #define RtlInt8ToDWord RtlInt8ToULong 443 #define RtlInt8ToDWordPtr RtlInt8ToULongPtr 444 #define RtlInt8ToDWordLong RtlInt8ToULongLong 445 #define RtlInt8ToULong64 RtlInt8ToULongLong 446 #define RtlInt8ToDWord64 RtlInt8ToULongLong 447 #define RtlInt8ToUInt64 RtlInt8ToULongLong 448 #define RtlInt8ToSizeT RtlInt8ToUIntPtr 449 #define RtlInt8ToSIZET RtlInt8ToULongPtr 450 #define RtlIntToSizeT RtlIntToUIntPtr 451 #define RtlIntToSIZET RtlIntToULongPtr 452 #define RtlULongToSSIZET RtlULongToLongPtr 453 #define RtlULongToByte RtlULongToUInt8 454 #define RtlULongLongToInt64 RtlULongLongToLongLong 455 #define RtlULongLongToLong64 RtlULongLongToLongLong 456 #define RtlULongLongToPtrdiffT RtlULongLongToIntPtr 457 #define RtlULongLongToSizeT RtlULongLongToUIntPtr 458 #define RtlULongLongToSSIZET RtlULongLongToLongPtr 459 #define RtlULongLongToSIZET RtlULongLongToULongPtr 460 #define RtlSIZETToULong RtlULongPtrToULong 461 #define RtlSSIZETToULongLong RtlLongPtrToULongLong 462 #define RtlSSIZETToULong RtlLongPtrToULong 463 #ifdef _WIN64 464 #define RtlIntToUIntPtr RtlIntToULongLong 465 #define RtlULongLongToIntPtr RtlULongLongToLongLong 466 #else 467 #define RtlIntToUIntPtr RtlIntToUInt 468 #define RtlULongLongToIntPtr RtlULongLongToInt 469 #define RtlULongLongToUIntPtr RtlULongLongToUInt 470 #define RtlULongLongToULongPtr RtlULongLongToULong 471 #endif 472 473 #else // _NTINTSAFE_H_INCLUDED_ 474 475 #define Int8ToByte Int8ToUInt8 476 #define Int8ToUInt16 Int8ToUShort 477 #define Int8ToWord Int8ToUShort 478 #define Int8ToUInt32 Int8ToUInt 479 #define Int8ToDWord Int8ToULong 480 #define Int8ToDWordPtr Int8ToULongPtr 481 #define Int8ToDWordLong Int8ToULongLong 482 #define Int8ToULong64 Int8ToULongLong 483 #define Int8ToDWord64 Int8ToULongLong 484 #define Int8ToUInt64 Int8ToULongLong 485 #define Int8ToSizeT Int8ToUIntPtr 486 #define Int8ToSIZET Int8ToULongPtr 487 #define IntToSizeT IntToUIntPtr 488 #define IntToSIZET IntToULongPtr 489 #define ULongToSSIZET ULongToLongPtr 490 #define ULongToByte ULongToUInt8 491 #define ULongLongToInt64 ULongLongToLongLong 492 #define ULongLongToLong64 ULongLongToLongLong 493 #define ULongLongToPtrdiffT ULongLongToIntPtr 494 #define ULongLongToSizeT ULongLongToUIntPtr 495 #define ULongLongToSSIZET ULongLongToLongPtr 496 #define ULongLongToSIZET ULongLongToULongPtr 497 #define SIZETToULong ULongPtrToULong 498 #define SSIZETToULongLong LongPtrToULongLong 499 #define SSIZETToULong LongPtrToULong 500 #ifdef _WIN64 501 #define IntToUIntPtr IntToULongLong 502 #define ULongLongToIntPtr ULongLongToLongLong 503 #else 504 #define IntToUIntPtr IntToUInt 505 #define ULongLongToIntPtr ULongLongToInt 506 #define ULongLongToUIntPtr ULongLongToUInt 507 #define ULongLongToULongPtr ULongLongToULong 508 #endif 509 510 #endif // _NTINTSAFE_H_INCLUDED_ 511 512 513 #define DEFINE_SAFE_ADD(_Name, _Type) \ 514 _Must_inspect_result_ \ 515 __forceinline \ 516 INTSAFE_RESULT \ 517 INTSAFE_NAME(_Name)( \ 518 _In_ _Type Augend, \ 519 _In_ _Type Addend, \ 520 _Out_ _Deref_out_range_(==, Augend + Addend) _Type *pOutput) \ 521 { \ 522 if ((_Type)(Augend + Addend) >= Augend) \ 523 { \ 524 *pOutput = Augend + Addend; \ 525 return INTSAFE_SUCCESS; \ 526 } \ 527 else \ 528 { \ 529 *pOutput = _Type ## _ERROR; \ 530 return INTSAFE_E_ARITHMETIC_OVERFLOW; \ 531 } \ 532 } 533 534 DEFINE_SAFE_ADD(UInt8Add, UINT8) 535 DEFINE_SAFE_ADD(UShortAdd, USHORT) 536 DEFINE_SAFE_ADD(UIntAdd, UINT) 537 DEFINE_SAFE_ADD(ULongAdd, ULONG) 538 DEFINE_SAFE_ADD(UIntPtrAdd, UINT_PTR) 539 DEFINE_SAFE_ADD(ULongPtrAdd, ULONG_PTR) 540 DEFINE_SAFE_ADD(DWordPtrAdd, DWORD_PTR) 541 DEFINE_SAFE_ADD(SizeTAdd, size_t) 542 DEFINE_SAFE_ADD(SIZETAdd, SIZE_T) 543 DEFINE_SAFE_ADD(ULongLongAdd, ULONGLONG) 544 545 546 #define DEFINE_SAFE_SUB(_Name, _Type) \ 547 _Must_inspect_result_ \ 548 __forceinline \ 549 INTSAFE_RESULT \ 550 INTSAFE_NAME(_Name)( \ 551 _In_ _Type Minuend, \ 552 _In_ _Type Subtrahend, \ 553 _Out_ _Deref_out_range_(==, Minuend - Subtrahend) _Type* pOutput) \ 554 { \ 555 if (Minuend >= Subtrahend) \ 556 { \ 557 *pOutput = Minuend - Subtrahend; \ 558 return INTSAFE_SUCCESS; \ 559 } \ 560 else \ 561 { \ 562 *pOutput = _Type ## _ERROR; \ 563 return INTSAFE_E_ARITHMETIC_OVERFLOW; \ 564 } \ 565 } 566 567 DEFINE_SAFE_SUB(UInt8Sub, UINT8) 568 DEFINE_SAFE_SUB(UShortSub, USHORT) 569 DEFINE_SAFE_SUB(UIntSub, UINT) 570 DEFINE_SAFE_SUB(UIntPtrSub, UINT_PTR) 571 DEFINE_SAFE_SUB(ULongSub, ULONG) 572 DEFINE_SAFE_SUB(ULongPtrSub, ULONG_PTR) 573 DEFINE_SAFE_SUB(DWordPtrSub, DWORD_PTR) 574 DEFINE_SAFE_SUB(SizeTSub, size_t) 575 DEFINE_SAFE_SUB(SIZETSub, SIZE_T) 576 DEFINE_SAFE_SUB(ULongLongSub, ULONGLONG) 577 578 #ifdef ENABLE_INTSAFE_SIGNED_FUNCTIONS 579 _Must_inspect_result_ 580 __forceinline 581 INTSAFE_RESULT 582 INTSAFE_NAME(LongLongAdd)( 583 _In_ LONGLONG Augend, 584 _In_ LONGLONG Addend, 585 _Out_ _Deref_out_range_(==, Augend + Addend) LONGLONG* pResult) 586 { 587 LONGLONG Result = Augend + Addend; 588 589 /* The only way the result can overflow, is when the sign of the augend 590 and the addend are the same. In that case the result is expected to 591 have the same sign as the two, otherwise it overflowed. 592 Sign equality is checked with a binary xor operation. */ 593 if ( ((Augend ^ Addend) >= 0) && ((Augend ^ Result) < 0) ) 594 { 595 *pResult = LONGLONG_ERROR; 596 return INTSAFE_E_ARITHMETIC_OVERFLOW; 597 } 598 else 599 { 600 *pResult = Result; 601 return INTSAFE_SUCCESS; 602 } 603 } 604 605 606 #define DEFINE_SAFE_ADD_S(_Name, _Type1, _Type2, _Convert) \ 607 C_ASSERT(sizeof(_Type2) > sizeof(_Type1)); \ 608 _Must_inspect_result_ \ 609 __forceinline \ 610 INTSAFE_RESULT \ 611 INTSAFE_NAME(_Name)( \ 612 _In_ _Type1 Augend, \ 613 _In_ _Type1 Addend, \ 614 _Out_ _Deref_out_range_(==, Augend + Addend) _Type1* pOutput) \ 615 { \ 616 return INTSAFE_NAME(_Convert)(((_Type2)Augend) + ((_Type2)Addend), pOutput); \ 617 } 618 619 DEFINE_SAFE_ADD_S(Int8Add, INT8, SHORT, ShortToInt8) 620 DEFINE_SAFE_ADD_S(ShortAdd, SHORT, INT, IntToShort) 621 DEFINE_SAFE_ADD_S(IntAdd, INT, LONGLONG, LongLongToInt) 622 DEFINE_SAFE_ADD_S(LongAdd, LONG, LONGLONG, LongLongToLong) 623 #ifndef _WIN64 624 DEFINE_SAFE_ADD_S(IntPtrAdd, INT_PTR, LONGLONG, LongLongToIntPtr) 625 DEFINE_SAFE_ADD_S(LongPtrAdd, LONG_PTR, LONGLONG, LongLongToLongPtr) 626 #endif 627 628 _Must_inspect_result_ 629 __forceinline 630 INTSAFE_RESULT 631 INTSAFE_NAME(LongLongSub)( 632 _In_ LONGLONG Minuend, 633 _In_ LONGLONG Subtrahend, 634 _Out_ _Deref_out_range_(==, Minuend - Subtrahend) LONGLONG* pResult) 635 { 636 LONGLONG Result = Minuend - Subtrahend; 637 638 /* The only way the result can overflow, is when the sign of the minuend 639 and the subtrahend differ. In that case the result is expected to 640 have the same sign as the minuend, otherwise it overflowed. 641 Sign equality is checked with a binary xor operation. */ 642 if ( ((Minuend ^ Subtrahend) < 0) && ((Minuend ^ Result) < 0) ) 643 { 644 *pResult = LONGLONG_ERROR; 645 return INTSAFE_E_ARITHMETIC_OVERFLOW; 646 } 647 else 648 { 649 *pResult = Result; 650 return INTSAFE_SUCCESS; 651 } 652 } 653 654 655 #define DEFINE_SAFE_SUB_S(_Name, _Type1, _Type2, _Convert) \ 656 C_ASSERT(sizeof(_Type2) > sizeof(_Type1)); \ 657 _Must_inspect_result_ \ 658 __forceinline \ 659 INTSAFE_RESULT \ 660 INTSAFE_NAME(_Name)( \ 661 _In_ _Type1 Minuend, \ 662 _In_ _Type1 Subtrahend, \ 663 _Out_ _Deref_out_range_(==, Minuend - Subtrahend) _Type1* pOutput) \ 664 { \ 665 return INTSAFE_NAME(_Convert)(((_Type2)Minuend) - ((_Type2)Subtrahend), pOutput); \ 666 } 667 668 DEFINE_SAFE_SUB_S(LongSub, LONG, LONGLONG, LongLongToLong) 669 #ifndef _WIN64 670 DEFINE_SAFE_SUB_S(IntPtrSub, INT_PTR, LONGLONG, LongLongToIntPtr) 671 DEFINE_SAFE_SUB_S(LongPtrSub, LONG_PTR, LONGLONG, LongLongToLongPtr) 672 #endif 673 674 #endif /* ENABLE_INTSAFE_SIGNED_FUNCTIONS */ 675 676 _Must_inspect_result_ 677 __forceinline 678 INTSAFE_RESULT 679 INTSAFE_NAME(ULongLongMult)( 680 _In_ ULONGLONG Multiplicand, 681 _In_ ULONGLONG Multiplier, 682 _Out_ _Deref_out_range_(==, Multiplicand * Multiplier) ULONGLONG* pOutput) 683 { 684 /* We can split the 64 bit numbers in low and high parts: 685 M1 = M1Low + M1Hi * 0x100000000 686 M2 = M2Low + M2Hi * 0x100000000 687 688 Then the multiplication looks like this: 689 M1 * M2 = (M1Low + M1Hi * 0x100000000) * (M2Low + M2Hi * 0x100000000) 690 = M1Low * M2Low 691 + M1Low * M2Hi * 0x100000000 692 + M2Low * M1Hi * 0x100000000 693 + M1Hi * M2Hi * 0x100000000 * 0x100000000 694 695 We get an overflow when 696 a) M1Hi * M2Hi != 0, so when M1Hi and M2Hi are both not 0 697 b) The product of the nonzero high part and the other low part 698 is larger than 32 bits. 699 c) The addition of the product from b) shifted left by 32 and 700 M1Low * M2Low is larger than 64 bits 701 */ 702 ULONG M1Low = Multiplicand & 0xffffffff; 703 ULONG M2Low = Multiplier & 0xffffffff; 704 ULONG M1Hi = Multiplicand >> 32; 705 ULONG M2Hi = Multiplier >> 32; 706 ULONGLONG Temp; 707 708 if (M1Hi == 0) 709 { 710 Temp = UInt32x32To64(M1Low, M2Hi); 711 } 712 else if (M2Hi == 0) 713 { 714 Temp = UInt32x32To64(M1Hi, M2Low); 715 } 716 else 717 { 718 *pOutput = ULONGLONG_ERROR; 719 return INTSAFE_E_ARITHMETIC_OVERFLOW; 720 } 721 722 if (Temp > ULONG_MAX) 723 { 724 *pOutput = ULONGLONG_ERROR; 725 return INTSAFE_E_ARITHMETIC_OVERFLOW; 726 } 727 728 return INTSAFE_NAME(ULongLongAdd)(Temp << 32, UInt32x32To64(M1Low, M2Low), pOutput); 729 } 730 731 732 #define DEFINE_SAFE_MULT_U32(_Name, _Type, _Convert) \ 733 _Must_inspect_result_ \ 734 __forceinline \ 735 INTSAFE_RESULT \ 736 INTSAFE_NAME(_Name)( \ 737 _In_ _Type Multiplicand, \ 738 _In_ _Type Multiplier, \ 739 _Out_ _Deref_out_range_(==, Multiplicand * Multiplier) _Type* pOutput) \ 740 { \ 741 ULONGLONG Result = UInt32x32To64(Multiplicand, Multiplier); \ 742 return INTSAFE_NAME(_Convert)(Result, pOutput); \ 743 } 744 745 DEFINE_SAFE_MULT_U32(ULongMult, ULONG, ULongLongToULong) 746 #ifndef _WIN64 747 DEFINE_SAFE_MULT_U32(SizeTMult, size_t, ULongLongToSizeT) 748 DEFINE_SAFE_MULT_U32(SIZETMult, SIZE_T, ULongLongToSIZET) 749 #endif 750 751 #define DEFINE_SAFE_MULT_U16(_Name, _Type, _Convert) \ 752 _Must_inspect_result_ \ 753 __forceinline \ 754 INTSAFE_RESULT \ 755 INTSAFE_NAME(_Name)( \ 756 _In_ _Type Multiplicand, \ 757 _In_ _Type Multiplier, \ 758 _Out_ _Deref_out_range_(==, Multiplicand * Multiplier) _Type* pOutput) \ 759 { \ 760 ULONG Result = ((ULONG)Multiplicand) * ((ULONG)Multiplier); \ 761 return INTSAFE_NAME(_Convert)(Result, pOutput); \ 762 } 763 764 DEFINE_SAFE_MULT_U16(UShortMult, USHORT, ULongToUShort) 765 766 767 #ifdef _NTINTSAFE_H_INCLUDED_ 768 769 #define RtlUInt16Add RtlUShortAdd 770 #define RtlWordAdd RtlUShortAdd 771 #define RtlUInt32Add RtlUIntAdd 772 #define RtlDWordAdd RtlULongAdd 773 #define RtlDWordLongAdd RtlULongLongAdd 774 #define RtlULong64Add RtlULongLongAdd 775 #define RtlDWord64Add RtlULongLongAdd 776 #define RtlUInt64Add RtlULongLongAdd 777 #define RtlUInt16Sub RtlUShortSub 778 #define RtlWordSub RtlUShortSub 779 #define RtlUInt32Sub RtlUIntSub 780 #define RtlDWordSub RtlULongSub 781 #define RtlDWordLongSub RtlULongLongSub 782 #define RtlULong64Sub RtlULongLongSub 783 #define RtlDWord64Sub RtlULongLongSub 784 #define RtlUInt64Sub RtlULongLongSub 785 #define RtlUInt16Mult RtlUShortMult 786 #define RtlWordMult RtlUShortMult 787 #ifdef _WIN64 788 #define RtlIntPtrAdd RtlLongLongAdd 789 #define RtlLongPtrAdd RtlLongLongAdd 790 #define RtlIntPtrSub RtlLongLongSub 791 #define RtlLongPtrSub RtlLongLongSub 792 #define RtlSizeTMult RtlULongLongMult 793 #define RtlSIZETMult RtlULongLongMult 794 #else 795 #endif 796 797 #else // _NTINTSAFE_H_INCLUDED_ 798 799 #define UInt16Add UShortAdd 800 #define WordAdd UShortAdd 801 #define UInt32Add UIntAdd 802 #define DWordAdd ULongAdd 803 #define DWordLongAdd ULongLongAdd 804 #define ULong64Add ULongLongAdd 805 #define DWord64Add ULongLongAdd 806 #define UInt64Add ULongLongAdd 807 #define UInt16Sub UShortSub 808 #define WordSub UShortSub 809 #define UInt32Sub UIntSub 810 #define DWordSub ULongSub 811 #define DWordLongSub ULongLongSub 812 #define ULong64Sub ULongLongSub 813 #define DWord64Sub ULongLongSub 814 #define UInt64Sub ULongLongSub 815 #define UInt16Mult UShortMult 816 #define WordMult UShortMult 817 #ifdef _WIN64 818 #define IntPtrAdd LongLongAdd 819 #define LongPtrAdd LongLongAdd 820 #define IntPtrSub LongLongSub 821 #define LongPtrSub LongLongSub 822 #define SizeTMult ULongLongMult 823 #define SIZETMult ULongLongMult 824 #else 825 #endif 826 827 #undef _INTSAFE_CHAR_MIN 828 #undef _INTSAFE_CHAR_MAX 829 #undef _INTSAFE_CHAR_ERROR 830 831 #endif // _NTINTSAFE_H_INCLUDED_ 832 833 #endif // !_INTSAFE_H_INCLUDED_ 834