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