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 #if defined(__GNUC__) && !defined(__forceinline) 34 # if ( __MINGW_GNUC_PREREQ(4, 3) && __STDC_VERSION__ >= 199901L) 35 # define __forceinline extern inline __attribute__((__always_inline__,__gnu_inline__)) 36 # else 37 # define __forceinline extern __inline__ __attribute__((__always_inline__)) 38 # endif 39 #endif 40 41 /* Handle ntintsafe here too */ 42 #ifdef _NTINTSAFE_H_INCLUDED_ 43 #ifndef _NTDEF_ /* Guard agains redefinition from ntstatus.h */ 44 typedef _Return_type_success_(return >= 0) long NTSTATUS; 45 #endif 46 #define NT_SUCCESS(Status) (((NTSTATUS)(Status)) >= 0) 47 #define STATUS_SUCCESS ((NTSTATUS)0x00000000) 48 #define STATUS_INTEGER_OVERFLOW ((NTSTATUS)0xC0000095) 49 #define INTSAFE_RESULT NTSTATUS 50 #define INTSAFE_SUCCESS STATUS_SUCCESS 51 #define INTSAFE_E_ARITHMETIC_OVERFLOW STATUS_INTEGER_OVERFLOW 52 #define INTSAFE_NAME(name) Rtl##name 53 #else // _NTINTSAFE_H_INCLUDED_ 54 #ifndef _HRESULT_DEFINED 55 typedef _Return_type_success_(return >= 0) long HRESULT; 56 #endif 57 #define SUCCEEDED(hr) (((HRESULT)(hr)) >= 0) 58 #define FAILED(hr) (((HRESULT)(hr)) < 0) 59 #define S_OK ((HRESULT)0L) 60 #define INTSAFE_RESULT HRESULT 61 #define INTSAFE_SUCCESS S_OK 62 #define INTSAFE_E_ARITHMETIC_OVERFLOW ((HRESULT)0x80070216L) 63 #define INTSAFE_NAME(name) name 64 #endif // _NTINTSAFE_H_INCLUDED_ 65 66 #if !defined(_W64) 67 #if defined(_MSC_VER) && !defined(__midl) && (defined(_M_IX86) || defined(_M_ARM)) 68 #define _W64 __w64 69 #else 70 #define _W64 71 #endif 72 #endif 73 74 /* Static assert */ 75 #ifndef C_ASSERT 76 #ifdef _MSC_VER 77 # define C_ASSERT(e) typedef char __C_ASSERT__[(e)?1:-1] 78 #else 79 # define C_ASSERT(e) extern void __C_ASSERT__(int [(e)?1:-1]) 80 #endif 81 #endif /* C_ASSERT */ 82 83 /* Typedefs */ 84 #ifndef _WINNT_ 85 #ifndef _NTDEF_ 86 typedef char CHAR; 87 typedef unsigned char UCHAR, UINT8; 88 typedef signed char INT8; 89 typedef short SHORT; 90 typedef signed short INT16; 91 typedef unsigned short USHORT, UINT16; 92 typedef int INT; 93 typedef unsigned int UINT32; 94 typedef signed int INT32; 95 typedef long LONG; 96 typedef unsigned long ULONG; 97 typedef long long LONGLONG, LONG64; 98 typedef signed long long INT64; 99 typedef unsigned long long ULONGLONG, DWORDLONG, ULONG64, DWORD64, UINT64; 100 #ifdef _WIN64 101 typedef long long INT_PTR, LONG_PTR, SSIZE_T, ptrdiff_t; 102 typedef unsigned long long UINT_PTR, ULONG_PTR, DWORD_PTR, SIZE_T, size_t; 103 #else // _WIN64 104 typedef _W64 int INT_PTR, ptrdiff_t; 105 typedef _W64 unsigned int UINT_PTR, size_t; 106 typedef _W64 long LONG_PTR, SSIZE_T; 107 typedef _W64 unsigned long ULONG_PTR, DWORD_PTR, SIZE_T; 108 #endif // _WIN64 109 #endif 110 typedef unsigned char BYTE; 111 typedef unsigned short WORD; 112 typedef unsigned int UINT; 113 typedef unsigned long DWORD; 114 #endif // _WINNT_ 115 116 /* Just to be sure! */ 117 C_ASSERT(sizeof(USHORT) == 2); 118 C_ASSERT(sizeof(INT) == 4); 119 C_ASSERT(sizeof(UINT) == 4); 120 C_ASSERT(sizeof(LONG) == 4); 121 C_ASSERT(sizeof(ULONG) == 4); 122 C_ASSERT(sizeof(DWORD) == 4); 123 C_ASSERT(sizeof(UINT_PTR) == sizeof(ULONG_PTR)); 124 125 /* Integer range margins (use (x-1) to prevent warnings) */ 126 #define INT8_MIN ((signed char)(-127 - 1)) 127 #define SHORT_MIN (-32768) 128 #define INT16_MIN ((short)(-32767 - 1)) 129 #define INT_MIN (-2147483647 - 1) 130 #define INT32_MIN (-2147483647 - 1) 131 #define LONG_MIN (-2147483647L - 1) 132 #define LONGLONG_MIN (-9223372036854775807LL - 1) 133 #define LONG64_MIN (-9223372036854775807LL - 1) 134 #define INT64_MIN (-9223372036854775807LL - 1) 135 #define INT128_MIN (-170141183460469231731687303715884105727i128 - 1) 136 #ifdef _WIN64 137 #define INT_PTR_MIN (-9223372036854775807LL - 1) 138 #define LONG_PTR_MIN (-9223372036854775807LL - 1) 139 #define PTRDIFF_T_MIN (-9223372036854775807LL - 1) 140 #define SSIZE_T_MIN (-9223372036854775807LL - 1) 141 #else /* _WIN64 */ 142 #define INT_PTR_MIN (-2147483647 - 1) 143 #define LONG_PTR_MIN (-2147483647L - 1) 144 #define PTRDIFF_T_MIN (-2147483647 - 1) 145 #define SSIZE_T_MIN (-2147483647L - 1) 146 #endif /* _WIN64 */ 147 148 #define INT8_MAX ((signed char)127) 149 #define UINT8_MAX ((unsigned char)0xffU) 150 #define BYTE_MAX ((unsigned char)0xff) 151 #define SHORT_MAX ((short)32767) 152 #define INT16_MAX ((short)32767) 153 #define USHORT_MAX ((unsigned short)0xffff) 154 #define UINT16_MAX ((unsigned short)0xffff) 155 #define WORD_MAX ((unsigned short)0xffff) 156 #define INT_MAX 2147483647 157 #define INT32_MAX 2147483647 158 #define UINT_MAX 0xffffffff 159 #define UINT32_MAX 0xffffffffU 160 #define LONG_MAX 2147483647L 161 #define ULONG_MAX 0xffffffffUL 162 #define DWORD_MAX 0xffffffffUL 163 #define LONGLONG_MAX 9223372036854775807LL 164 #define LONG64_MAX 9223372036854775807LL 165 #define INT64_MAX 9223372036854775807LL 166 #define ULONGLONG_MAX 0xffffffffffffffffULL 167 #define DWORDLONG_MAX 0xffffffffffffffffULL 168 #define ULONG64_MAX 0xffffffffffffffffULL 169 #define DWORD64_MAX 0xffffffffffffffffULL 170 #define UINT64_MAX 0xffffffffffffffffULL 171 #define INT128_MAX 170141183460469231731687303715884105727i128 172 #define UINT128_MAX 0xffffffffffffffffffffffffffffffffui128 173 #undef SIZE_T_MAX 174 #ifdef _WIN64 175 #define INT_PTR_MAX 9223372036854775807LL 176 #define UINT_PTR_MAX 0xffffffffffffffffULL 177 #define LONG_PTR_MAX 9223372036854775807LL 178 #define ULONG_PTR_MAX 0xffffffffffffffffULL 179 #define DWORD_PTR_MAX 0xffffffffffffffffULL 180 #define PTRDIFF_T_MAX 9223372036854775807LL 181 #define SIZE_T_MAX 0xffffffffffffffffULL 182 #define SSIZE_T_MAX 9223372036854775807LL 183 #define _SIZE_T_MAX 0xffffffffffffffffULL 184 #else /* _WIN64 */ 185 #define INT_PTR_MAX 2147483647 186 #define UINT_PTR_MAX 0xffffffff 187 #define LONG_PTR_MAX 2147483647L 188 #define ULONG_PTR_MAX 0xffffffffUL 189 #define DWORD_PTR_MAX 0xffffffffUL 190 #define PTRDIFF_T_MAX 2147483647 191 #define SIZE_T_MAX 0xffffffff 192 #define SSIZE_T_MAX 2147483647L 193 #define _SIZE_T_MAX 0xffffffffUL 194 #endif /* _WIN64 */ 195 196 /* Error values */ 197 #define INT8_ERROR ((signed char)(-1)) 198 #define UINT8_ERROR ((unsigned char)0xff) 199 #define BYTE_ERROR ((unsigned char)0xff) 200 #define SHORT_ERROR ((short)(-1)) 201 #define INT16_ERROR ((short)(-1)) 202 #define USHORT_ERROR ((unsigned short)0xffff) 203 #define UINT16_ERROR ((unsigned short)0xffff) 204 #define WORD_ERROR ((unsigned short)0xffff) 205 #define INT_ERROR (-1) 206 #define INT32_ERROR (-1) 207 #define UINT_ERROR 0xffffffffU 208 #define UINT32_ERROR 0xffffffffU 209 #define LONG_ERROR (-1L) 210 #define ULONG_ERROR 0xffffffffUL 211 #define DWORD_ERROR 0xffffffffUL 212 #define LONGLONG_ERROR (-1LL) 213 #define LONG64_ERROR (-1LL) 214 #define INT64_ERROR (-1LL) 215 #define ULONGLONG_ERROR 0xffffffffffffffffULL 216 #define DWORDLONG_ERROR 0xffffffffffffffffULL 217 #define ULONG64_ERROR 0xffffffffffffffffULL 218 #define UINT64_ERROR 0xffffffffffffffffULL 219 #ifdef _WIN64 220 #define INT_PTR_ERROR (-1LL) 221 #define UINT_PTR_ERROR 0xffffffffffffffffULL 222 #define LONG_PTR_ERROR (-1LL) 223 #define ULONG_PTR_ERROR 0xffffffffffffffffULL 224 #define DWORD_PTR_ERROR 0xffffffffffffffffULL 225 #define PTRDIFF_T_ERROR (-1LL) 226 #define SIZE_T_ERROR 0xffffffffffffffffULL 227 #define SSIZE_T_ERROR (-1LL) 228 #define _SIZE_T_ERROR 0xffffffffffffffffULL 229 #else /* _WIN64 */ 230 #define INT_PTR_ERROR (-1) 231 #define UINT_PTR_ERROR 0xffffffffU 232 #define LONG_PTR_ERROR (-1L) 233 #define ULONG_PTR_ERROR 0xffffffffUL 234 #define DWORD_PTR_ERROR 0xffffffffUL 235 #define PTRDIFF_T_ERROR (-1) 236 #define SIZE_T_ERROR 0xffffffffU 237 #define SSIZE_T_ERROR (-1L) 238 #define _SIZE_T_ERROR 0xffffffffUL 239 #endif /* _WIN64 */ 240 241 /* special definitons (the CHAR ones should not be defined here!) */ 242 #define _INTSAFE_CHAR CHAR 243 #define _INTSAFE_CHAR_ERROR ((signed char)(-1)) 244 #ifdef _CHAR_UNSIGNED 245 #define _INTSAFE_CHAR_MIN ((unsigned char)0) 246 #define _INTSAFE_CHAR_MAX ((unsigned char)0xff) 247 #else 248 #define _INTSAFE_CHAR_MIN ((signed char)(-128)) 249 #define _INTSAFE_CHAR_MAX ((signed char)127) 250 #endif /* _CHAR_UNSIGNED */ 251 252 #define size_t_ERROR SIZE_T_ERROR 253 #define UCHAR_ERROR '\0' 254 #define CHAR_ERROR '\0' 255 256 /* 32 bit x 32 bit to 64 bit unsigned multiplication */ 257 #ifndef UInt32x32To64 258 #define UInt32x32To64(a,b) ((unsigned __int64)(unsigned int)(a)*(unsigned __int64)(unsigned int)(b)) 259 #endif 260 261 /* Convert unsigned to signed or unsigned */ 262 #define DEFINE_SAFE_CONVERT_UTOX(_Name, _TypeFrom, _TypeTo) \ 263 _Must_inspect_result_ \ 264 __forceinline \ 265 INTSAFE_RESULT \ 266 INTSAFE_NAME(_Name)( \ 267 _In_ _TypeFrom Input, \ 268 _Out_ _Deref_out_range_(==, Input) _TypeTo *pOutput) \ 269 { \ 270 if (Input <= _TypeTo ## _MAX) \ 271 { \ 272 *pOutput = (_TypeTo)Input; \ 273 return INTSAFE_SUCCESS; \ 274 } \ 275 else \ 276 { \ 277 *pOutput = _TypeTo ## _ERROR; \ 278 return INTSAFE_E_ARITHMETIC_OVERFLOW; \ 279 } \ 280 } 281 282 DEFINE_SAFE_CONVERT_UTOX(ByteToChar, BYTE, _INTSAFE_CHAR) 283 DEFINE_SAFE_CONVERT_UTOX(ByteToInt8, BYTE, INT8) 284 DEFINE_SAFE_CONVERT_UTOX(UInt8ToChar, UINT8, _INTSAFE_CHAR) 285 DEFINE_SAFE_CONVERT_UTOX(UInt8ToInt8, UINT8, INT8) 286 DEFINE_SAFE_CONVERT_UTOX(UShortToChar, USHORT, _INTSAFE_CHAR) 287 DEFINE_SAFE_CONVERT_UTOX(UShortToUChar, USHORT, UINT8) 288 DEFINE_SAFE_CONVERT_UTOX(UShortToInt8, USHORT, INT8) 289 DEFINE_SAFE_CONVERT_UTOX(UShortToUInt8, USHORT, UINT8) 290 DEFINE_SAFE_CONVERT_UTOX(UShortToShort, USHORT, SHORT) 291 DEFINE_SAFE_CONVERT_UTOX(UIntToUChar, UINT, UINT8) 292 DEFINE_SAFE_CONVERT_UTOX(UIntToInt8, UINT, INT8) 293 DEFINE_SAFE_CONVERT_UTOX(UIntToUInt8, UINT, UINT8) 294 DEFINE_SAFE_CONVERT_UTOX(UIntToShort, UINT, SHORT) 295 DEFINE_SAFE_CONVERT_UTOX(UIntToUShort, UINT, USHORT) 296 DEFINE_SAFE_CONVERT_UTOX(UIntToInt, UINT, INT) 297 DEFINE_SAFE_CONVERT_UTOX(UIntToLong, UINT, LONG) 298 DEFINE_SAFE_CONVERT_UTOX(UIntPtrToUChar, UINT_PTR, UINT8) 299 DEFINE_SAFE_CONVERT_UTOX(UIntPtrToInt8, UINT_PTR, INT8) 300 DEFINE_SAFE_CONVERT_UTOX(UIntPtrToUInt8, UINT_PTR, UINT8) 301 DEFINE_SAFE_CONVERT_UTOX(UIntPtrToShort, UINT_PTR, SHORT) 302 DEFINE_SAFE_CONVERT_UTOX(UIntPtrToUShort, UINT_PTR, USHORT) 303 DEFINE_SAFE_CONVERT_UTOX(UIntPtrToInt16, UINT_PTR, INT16) 304 DEFINE_SAFE_CONVERT_UTOX(UIntPtrToUInt16, UINT_PTR, UINT16) 305 DEFINE_SAFE_CONVERT_UTOX(UIntPtrToInt, UINT_PTR, INT) 306 DEFINE_SAFE_CONVERT_UTOX(UIntPtrToLong, UINT_PTR, LONG) 307 DEFINE_SAFE_CONVERT_UTOX(UIntPtrToIntPtr, UINT_PTR, INT_PTR) 308 DEFINE_SAFE_CONVERT_UTOX(UIntPtrToLongPtr, UINT_PTR, LONG_PTR) 309 DEFINE_SAFE_CONVERT_UTOX(ULongToUChar, ULONG, UINT8) 310 DEFINE_SAFE_CONVERT_UTOX(ULongToUInt8, ULONG, UINT8) 311 DEFINE_SAFE_CONVERT_UTOX(ULongToShort, ULONG, SHORT) 312 DEFINE_SAFE_CONVERT_UTOX(ULongToUShort, ULONG, USHORT) 313 DEFINE_SAFE_CONVERT_UTOX(ULongToInt, ULONG, INT) 314 DEFINE_SAFE_CONVERT_UTOX(ULongToUInt, ULONG, UINT) 315 DEFINE_SAFE_CONVERT_UTOX(ULongToIntPtr, ULONG, INT_PTR) 316 DEFINE_SAFE_CONVERT_UTOX(ULongToUIntPtr, ULONG, UINT_PTR) 317 DEFINE_SAFE_CONVERT_UTOX(ULongToLongPtr, ULONG, LONG_PTR) 318 DEFINE_SAFE_CONVERT_UTOX(ULongPtrToULong, ULONG_PTR, ULONG) 319 DEFINE_SAFE_CONVERT_UTOX(ULongLongToUInt, ULONGLONG, UINT) 320 DEFINE_SAFE_CONVERT_UTOX(ULongLongToULong, ULONGLONG, ULONG) 321 DEFINE_SAFE_CONVERT_UTOX(ULongLongToULongPtr, ULONGLONG, ULONG_PTR) 322 323 324 /* Convert signed to unsigned */ 325 #define DEFINE_SAFE_CONVERT_STOU(_Name, _TypeFrom, _TypeTo) \ 326 _Must_inspect_result_ \ 327 __forceinline \ 328 INTSAFE_RESULT \ 329 INTSAFE_NAME(_Name)( \ 330 _In_ _TypeFrom Input, \ 331 _Out_ _Deref_out_range_(==, Input) _TypeTo *pOutput) \ 332 { \ 333 if ((Input >= 0) && \ 334 ((sizeof(_TypeFrom) <= sizeof(_TypeTo)) || (Input <= (_TypeFrom)_TypeTo ## _MAX))) \ 335 { \ 336 *pOutput = (_TypeTo)Input; \ 337 return INTSAFE_SUCCESS; \ 338 } \ 339 else \ 340 { \ 341 *pOutput = _TypeTo ## _ERROR; \ 342 return INTSAFE_E_ARITHMETIC_OVERFLOW; \ 343 } \ 344 } 345 346 DEFINE_SAFE_CONVERT_STOU(Int8ToUChar, INT8, UINT8) 347 DEFINE_SAFE_CONVERT_STOU(Int8ToUInt8, INT8, UINT8) 348 DEFINE_SAFE_CONVERT_STOU(Int8ToUShort, INT8, USHORT) 349 DEFINE_SAFE_CONVERT_STOU(Int8ToUInt, INT8, UINT) 350 DEFINE_SAFE_CONVERT_STOU(Int8ToULong, INT8, ULONG) 351 DEFINE_SAFE_CONVERT_STOU(Int8ToUIntPtr, INT8, UINT_PTR) 352 DEFINE_SAFE_CONVERT_STOU(Int8ToULongPtr, INT8, ULONG_PTR) 353 DEFINE_SAFE_CONVERT_STOU(Int8ToULongLong, INT8, ULONGLONG) 354 DEFINE_SAFE_CONVERT_STOU(ShortToUChar, SHORT, UINT8) 355 DEFINE_SAFE_CONVERT_STOU(ShortToUInt8, SHORT, UINT8) 356 DEFINE_SAFE_CONVERT_STOU(ShortToUShort, SHORT, USHORT) 357 DEFINE_SAFE_CONVERT_STOU(ShortToUInt, SHORT, UINT) 358 DEFINE_SAFE_CONVERT_STOU(ShortToULong, SHORT, ULONG) 359 DEFINE_SAFE_CONVERT_STOU(ShortToUIntPtr, SHORT, UINT_PTR) 360 DEFINE_SAFE_CONVERT_STOU(ShortToULongPtr, SHORT, ULONG_PTR) 361 DEFINE_SAFE_CONVERT_STOU(ShortToDWordPtr, SHORT, DWORD_PTR) 362 DEFINE_SAFE_CONVERT_STOU(ShortToULongLong, SHORT, ULONGLONG) 363 DEFINE_SAFE_CONVERT_STOU(IntToUChar, INT, UINT8) 364 DEFINE_SAFE_CONVERT_STOU(IntToUInt8, INT, UINT8) 365 DEFINE_SAFE_CONVERT_STOU(IntToUShort, INT, USHORT) 366 DEFINE_SAFE_CONVERT_STOU(IntToUInt, INT, UINT) 367 DEFINE_SAFE_CONVERT_STOU(IntToULong, INT, ULONG) 368 DEFINE_SAFE_CONVERT_STOU(IntToULongLong, INT, ULONGLONG) 369 DEFINE_SAFE_CONVERT_STOU(LongToUChar, LONG, UINT8) 370 DEFINE_SAFE_CONVERT_STOU(LongToUInt8, LONG, UINT8) 371 DEFINE_SAFE_CONVERT_STOU(LongToUShort, LONG, USHORT) 372 DEFINE_SAFE_CONVERT_STOU(LongToUInt, LONG, UINT) 373 DEFINE_SAFE_CONVERT_STOU(LongToULong, LONG, ULONG) 374 DEFINE_SAFE_CONVERT_STOU(LongToUIntPtr, LONG, UINT_PTR) 375 DEFINE_SAFE_CONVERT_STOU(LongToULongPtr, LONG, ULONG_PTR) 376 DEFINE_SAFE_CONVERT_STOU(LongToULongLong, LONG, ULONGLONG) 377 DEFINE_SAFE_CONVERT_STOU(IntPtrToUChar, INT_PTR, UINT8) 378 DEFINE_SAFE_CONVERT_STOU(IntPtrToUInt8, INT_PTR, UINT8) 379 DEFINE_SAFE_CONVERT_STOU(IntPtrToUShort, INT_PTR, USHORT) 380 DEFINE_SAFE_CONVERT_STOU(IntPtrToUInt, INT_PTR, UINT) 381 DEFINE_SAFE_CONVERT_STOU(IntPtrToULong, INT_PTR, ULONG) 382 DEFINE_SAFE_CONVERT_STOU(IntPtrToUIntPtr, INT_PTR, UINT_PTR) 383 DEFINE_SAFE_CONVERT_STOU(IntPtrToULongPtr, INT_PTR, ULONG_PTR) 384 DEFINE_SAFE_CONVERT_STOU(IntPtrToULongLong, INT_PTR, ULONGLONG) 385 DEFINE_SAFE_CONVERT_STOU(LongPtrToUChar, LONG_PTR, UINT8) 386 DEFINE_SAFE_CONVERT_STOU(LongPtrToUInt8, LONG_PTR, UINT8) 387 DEFINE_SAFE_CONVERT_STOU(LongPtrToUShort, LONG_PTR, USHORT) 388 DEFINE_SAFE_CONVERT_STOU(LongPtrToUInt, LONG_PTR, UINT) 389 DEFINE_SAFE_CONVERT_STOU(LongPtrToULong, LONG_PTR, ULONG) 390 DEFINE_SAFE_CONVERT_STOU(LongPtrToUIntPtr, LONG_PTR, UINT_PTR) 391 DEFINE_SAFE_CONVERT_STOU(LongPtrToULongPtr, LONG_PTR, ULONG_PTR) 392 DEFINE_SAFE_CONVERT_STOU(LongPtrToULongLong, LONG_PTR, ULONGLONG) 393 #ifdef _CHAR_UNSIGNED 394 DEFINE_SAFE_CONVERT_STOU(ShortToChar, SHORT, UINT8) 395 DEFINE_SAFE_CONVERT_STOU(LongPtrToChar, LONG_PTR, UINT8) 396 #endif 397 398 399 /* Convert signed to signed */ 400 #define DEFINE_SAFE_CONVERT_STOS(_Name, _TypeFrom, _TypeTo) \ 401 _Must_inspect_result_ \ 402 __forceinline \ 403 INTSAFE_RESULT \ 404 INTSAFE_NAME(_Name)( \ 405 _In_ _TypeFrom Input, \ 406 _Out_ _Deref_out_range_(==, Input) _TypeTo *pOutput) \ 407 { \ 408 if ((Input >= _TypeTo ## _MIN) && (Input <= _TypeTo ## _MAX)) \ 409 { \ 410 *pOutput = (_TypeTo)Input; \ 411 return INTSAFE_SUCCESS; \ 412 } \ 413 else \ 414 { \ 415 *pOutput = _TypeTo ## _ERROR; \ 416 return INTSAFE_E_ARITHMETIC_OVERFLOW; \ 417 } \ 418 } 419 420 DEFINE_SAFE_CONVERT_STOS(ShortToInt8, SHORT, INT8) 421 DEFINE_SAFE_CONVERT_STOS(IntToInt8, INT, INT8) 422 DEFINE_SAFE_CONVERT_STOS(IntToShort, INT, SHORT) 423 DEFINE_SAFE_CONVERT_STOS(LongToInt8, LONG, INT8) 424 DEFINE_SAFE_CONVERT_STOS(LongToShort, LONG, SHORT) 425 DEFINE_SAFE_CONVERT_STOS(LongToInt, LONG, INT) 426 DEFINE_SAFE_CONVERT_STOS(IntPtrToInt8, INT_PTR, INT8) 427 DEFINE_SAFE_CONVERT_STOS(IntPtrToShort, INT_PTR, SHORT) 428 DEFINE_SAFE_CONVERT_STOS(IntPtrToInt, INT_PTR, INT) 429 DEFINE_SAFE_CONVERT_STOS(IntPtrToLong, INT_PTR, LONG) 430 DEFINE_SAFE_CONVERT_STOS(IntPtrToLongPtr, INT_PTR, LONG_PTR) 431 DEFINE_SAFE_CONVERT_STOS(LongPtrToInt8, LONG_PTR, INT8) 432 DEFINE_SAFE_CONVERT_STOS(LongPtrToShort, LONG_PTR, SHORT) 433 DEFINE_SAFE_CONVERT_STOS(LongPtrToInt, LONG_PTR, INT) 434 DEFINE_SAFE_CONVERT_STOS(LongPtrToLong, LONG_PTR, LONG) 435 DEFINE_SAFE_CONVERT_STOS(LongPtrToIntPtr, LONG_PTR, INT_PTR) 436 DEFINE_SAFE_CONVERT_STOS(LongLongToInt, LONGLONG, INT) 437 DEFINE_SAFE_CONVERT_STOS(LongLongToLong, LONGLONG, LONG) 438 DEFINE_SAFE_CONVERT_STOS(LongLongToIntPtr, LONGLONG, INT_PTR) 439 DEFINE_SAFE_CONVERT_STOS(LongLongToLongPtr, LONGLONG, LONG_PTR) 440 DEFINE_SAFE_CONVERT_STOS(ShortToChar, SHORT, _INTSAFE_CHAR) 441 DEFINE_SAFE_CONVERT_STOS(LongPtrToChar, LONG_PTR, _INTSAFE_CHAR) 442 443 444 #ifdef _NTINTSAFE_H_INCLUDED_ 445 446 #define RtlInt8ToByte RtlInt8ToUInt8 447 #define RtlInt8ToUInt16 RtlInt8ToUShort 448 #define RtlInt8ToWord RtlInt8ToUShort 449 #define RtlInt8ToUInt32 RtlInt8ToUInt 450 #define RtlInt8ToDWord RtlInt8ToULong 451 #define RtlInt8ToDWordPtr RtlInt8ToULongPtr 452 #define RtlInt8ToDWordLong RtlInt8ToULongLong 453 #define RtlInt8ToULong64 RtlInt8ToULongLong 454 #define RtlInt8ToDWord64 RtlInt8ToULongLong 455 #define RtlInt8ToUInt64 RtlInt8ToULongLong 456 #define RtlInt8ToSizeT RtlInt8ToUIntPtr 457 #define RtlInt8ToSIZET RtlInt8ToULongPtr 458 #define RtlIntToSizeT RtlIntToUIntPtr 459 #define RtlIntToSIZET RtlIntToULongPtr 460 #define RtlULongToSSIZET RtlULongToLongPtr 461 #define RtlULongToByte RtlULongToUInt8 462 #define RtlULongLongToInt64 RtlULongLongToLongLong 463 #define RtlULongLongToLong64 RtlULongLongToLongLong 464 #define RtlULongLongToPtrdiffT RtlULongLongToIntPtr 465 #define RtlULongLongToSizeT RtlULongLongToUIntPtr 466 #define RtlULongLongToSSIZET RtlULongLongToLongPtr 467 #define RtlULongLongToSIZET RtlULongLongToULongPtr 468 #define RtlSIZETToULong RtlULongPtrToULong 469 #define RtlSSIZETToULongLong RtlLongPtrToULongLong 470 #define RtlSSIZETToULong RtlLongPtrToULong 471 #ifdef _WIN64 472 #define RtlIntToUIntPtr RtlIntToULongLong 473 #define RtlULongLongToIntPtr RtlULongLongToLongLong 474 #else 475 #define RtlIntToUIntPtr RtlIntToUInt 476 #define RtlULongLongToIntPtr RtlULongLongToInt 477 #define RtlULongLongToUIntPtr RtlULongLongToUInt 478 #define RtlULongLongToULongPtr RtlULongLongToULong 479 #endif 480 481 #else // _NTINTSAFE_H_INCLUDED_ 482 483 #define Int8ToByte Int8ToUInt8 484 #define Int8ToUInt16 Int8ToUShort 485 #define Int8ToWord Int8ToUShort 486 #define Int8ToUInt32 Int8ToUInt 487 #define Int8ToDWord Int8ToULong 488 #define Int8ToDWordPtr Int8ToULongPtr 489 #define Int8ToDWordLong Int8ToULongLong 490 #define Int8ToULong64 Int8ToULongLong 491 #define Int8ToDWord64 Int8ToULongLong 492 #define Int8ToUInt64 Int8ToULongLong 493 #define Int8ToSizeT Int8ToUIntPtr 494 #define Int8ToSIZET Int8ToULongPtr 495 #define IntToSizeT IntToUIntPtr 496 #define IntToSIZET IntToULongPtr 497 #define ULongToSSIZET ULongToLongPtr 498 #define ULongToByte ULongToUInt8 499 #define ULongLongToInt64 ULongLongToLongLong 500 #define ULongLongToLong64 ULongLongToLongLong 501 #define ULongLongToPtrdiffT ULongLongToIntPtr 502 #define ULongLongToSizeT ULongLongToUIntPtr 503 #define ULongLongToSSIZET ULongLongToLongPtr 504 #define ULongLongToSIZET ULongLongToULongPtr 505 #define SIZETToULong ULongPtrToULong 506 #define SSIZETToULongLong LongPtrToULongLong 507 #define SSIZETToULong LongPtrToULong 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