4 * \brief Windows helper functions for integer overflow prevention
6 * \package This file is part of the ReactOS PSDK package.
9 * Timo Kreuzer (timo.kreuzer@reactos.org)
11 * \copyright THIS SOFTWARE IS NOT COPYRIGHTED
13 * This source code is offered for use in the public domain. You may
14 * use, modify or distribute it freely.
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.
22 * - missing conversion functions
23 * - multiplication functions
24 * - signed add, sub and multiply functions
28 #ifndef _INTSAFE_H_INCLUDED_
29 #define _INTSAFE_H_INCLUDED_
31 #include <specstrings.h>
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__))
37 # define __forceinline extern __inline__ __attribute__((__always_inline__))
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
;
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
;
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_
67 #if defined(_MSC_VER) && !defined(__midl) && (defined(_M_IX86) || defined(_M_ARM))
77 # define C_ASSERT(e) typedef char __C_ASSERT__[(e)?1:-1]
79 # define C_ASSERT(e) extern void __C_ASSERT__(int [(e)?1:-1])
87 typedef unsigned char UCHAR
, UINT8
;
88 typedef signed char INT8
;
90 typedef signed short INT16
;
91 typedef unsigned short USHORT
, UINT16
;
93 typedef unsigned int UINT32
;
94 typedef signed int INT32
;
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
;
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;
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
;
110 typedef unsigned char BYTE
;
111 typedef unsigned short WORD
;
112 typedef unsigned int UINT
;
113 typedef unsigned long DWORD
;
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(UINT_PTR
) == sizeof(ULONG_PTR
));
124 /* Undefine these to avoid conflicts with limits.h */
135 /* Integer range margins (use (x-1) to prevent warnings) */
136 #define INT8_MIN (-127 - 1)
137 #define SHORT_MIN (-32767 - 1)
138 #define INT16_MIN (-32767 - 1)
139 #define INT_MIN (-2147483647 - 1)
140 #define INT32_MIN (-2147483647 - 1)
141 #define LONG_MIN (-2147483647L - 1)
142 #define LONGLONG_MIN (-9223372036854775807LL - 1)
143 #define LONG64_MIN (-9223372036854775807LL - 1)
144 #define INT64_MIN (-9223372036854775807LL - 1)
145 //#define INT128_MIN (-170141183460469231731687303715884105728)
147 #define INT_PTR_MIN INT64_MIN
148 #define LONG_PTR_MIN LONG64_MIN
149 #define PTRDIFF_T_MIN INT64_MIN
150 #define SSIZE_T_MIN INT64_MIN
152 #define INT_PTR_MIN INT_MIN
153 #define LONG_PTR_MIN LONG_MIN
154 #define PTRDIFF_T_MIN INT_MIN
155 #define SSIZE_T_MIN INT_MIN
159 #define UINT8_MAX 0xff
160 #define UCHAR_MAX 0xff
161 #define BYTE_MAX 0xff
162 #define SHORT_MAX 32767
163 #define INT16_MAX 32767
164 #define USHORT_MAX 0xffff
165 #define UINT16_MAX 0xffff
166 #define WORD_MAX 0xffff
167 #define INT_MAX 2147483647
168 #define INT32_MAX 2147483647
169 #define UINT_MAX 0xffffffff
170 #define UINT32_MAX 0xffffffff
171 #define LONG_MAX 2147483647L
172 #define ULONG_MAX 0xffffffffUL
173 #define DWORD_MAX 0xffffffffUL
174 #define LONGLONG_MAX 9223372036854775807LL
175 #define LONG64_MAX 9223372036854775807LL
176 #define INT64_MAX 9223372036854775807LL
177 #define ULONGLONG_MAX 0xffffffffffffffffULL
178 #define DWORDLONG_MAX 0xffffffffffffffffULL
179 #define ULONG64_MAX 0xffffffffffffffffULL
180 #define DWORD64_MAX 0xffffffffffffffffULL
181 #define UINT64_MAX 0xffffffffffffffffULL
182 #define INT128_MAX 170141183460469231731687303715884105727
183 #define UINT128_MAX 0xffffffffffffffffffffffffffffffff
186 #define INT_PTR_MAX INT64_MAX
187 #define UINT_PTR_MAX UINT64_MAX
188 #define LONG_PTR_MAX LONG64_MAX
189 #define ULONG_PTR_MAX ULONG64_MAX
190 #define DWORD_PTR_MAX DWORD64_MAX
191 #define PTRDIFF_T_MAX INT64_MAX
192 #define SIZE_T_MAX UINT64_MAX
193 #define SSIZE_T_MAX INT64_MAX
194 #define _SIZE_T_MAX UINT64_MAX
196 #define INT_PTR_MAX INT_MAX
197 #define UINT_PTR_MAX UINT_MAX
198 #define LONG_PTR_MAX LONG_MAX
199 #define ULONG_PTR_MAX ULONG_MAX
200 #define DWORD_PTR_MAX DWORD_MAX
201 #define PTRDIFF_T_MAX INT_MAX
202 #define SIZE_T_MAX UINT_MAX
203 #define SSIZE_T_MAX INT_MAX
204 #define _SIZE_T_MAX UINT_MAX
208 #ifdef _CHAR_UNSIGNED
210 #define CHAR_MAX 0xff
212 #define CHAR_MIN (-128)
218 #define INT8_ERROR (-1)
219 #define UINT8_ERROR 0xff
220 #define BYTE_ERROR 0xff
221 #define SHORT_ERROR (-1)
222 #define INT16_ERROR (-1)
223 #define USHORT_ERROR 0xffff
224 #define UINT16_ERROR 0xffff
225 #define WORD_ERROR 0xffff
226 #define INT_ERROR (-1)
227 #define INT32_ERROR (-1)
228 #define UINT_ERROR 0xffffffff
229 #define UINT32_ERROR 0xffffffff
230 #define LONG_ERROR (-1L)
231 #define ULONG_ERROR 0xffffffffUL
232 #define DWORD_ERROR 0xffffffffUL
233 #define LONGLONG_ERROR (-1LL)
234 #define LONG64_ERROR (-1LL)
235 #define INT64_ERROR (-1LL)
236 #define ULONGLONG_ERROR 0xffffffffffffffffULL
237 #define DWORDLONG_ERROR 0xffffffffffffffffULL
238 #define ULONG64_ERROR 0xffffffffffffffffULL
239 #define UINT64_ERROR 0xffffffffffffffffULL
241 #define INT_PTR_ERROR (-1LL)
242 #define UINT_PTR_ERROR 0xffffffffffffffffULL
243 #define LONG_PTR_ERROR (-1LL)
244 #define ULONG_PTR_ERROR 0xffffffffffffffffULL
245 #define DWORD_PTR_ERROR 0xffffffffffffffffULL
246 #define PTRDIFF_T_ERROR (-1LL)
247 #define SIZE_T_ERROR 0xffffffffffffffffULL
248 #define SSIZE_T_ERROR (-1LL)
249 #define _SIZE_T_ERROR 0xffffffffffffffffULL
251 #define INT_PTR_ERROR (-1)
252 #define UINT_PTR_ERROR 0xffffffff
253 #define LONG_PTR_ERROR (-1L)
254 #define ULONG_PTR_ERROR 0xffffffffUL
255 #define DWORD_PTR_ERROR 0xffffffffUL
256 #define PTRDIFF_T_ERROR (-1)
257 #define SIZE_T_ERROR 0xffffffff
258 #define SSIZE_T_ERROR (-1L)
259 #define _SIZE_T_ERROR 0xffffffffUL
262 #define size_t_ERROR SIZE_T_ERROR
263 #define UCHAR_ERROR '\0'
264 #define CHAR_ERROR '\0'
267 /* 32 bit x 32 bit to 64 bit unsigned multiplication */
268 #ifndef UInt32x32To64
269 #define UInt32x32To64(a,b) ((DWORDLONG)(a)*(DWORDLONG)(b))
273 #define DEFINE_SAFE_CONVERT_UTOX(_Name, _TypeFrom, _TypeTo) \
274 _Must_inspect_result_ \
277 INTSAFE_NAME(_Name)( \
278 _In_ _TypeFrom Input, \
279 _Out_ _Deref_out_range_(==, Input) _TypeTo *pOutput) \
281 if (Input <= _TypeTo ## _MAX) \
283 *pOutput = (_TypeTo)Input; \
284 return INTSAFE_SUCCESS; \
288 *pOutput = _TypeTo ## _ERROR; \
289 return INTSAFE_E_ARITHMETIC_OVERFLOW; \
293 DEFINE_SAFE_CONVERT_UTOX(ByteToChar
, BYTE
, CHAR
)
294 DEFINE_SAFE_CONVERT_UTOX(ByteToInt8
, BYTE
, INT8
)
295 DEFINE_SAFE_CONVERT_UTOX(UInt8ToChar
, UINT8
, CHAR
)
296 DEFINE_SAFE_CONVERT_UTOX(UInt8ToInt8
, UINT8
, INT8
)
297 DEFINE_SAFE_CONVERT_UTOX(UShortToChar
, USHORT
, CHAR
)
298 DEFINE_SAFE_CONVERT_UTOX(UShortToUChar
, USHORT
, UCHAR
)
299 DEFINE_SAFE_CONVERT_UTOX(UShortToInt8
, USHORT
, INT8
)
300 DEFINE_SAFE_CONVERT_UTOX(UShortToUInt8
, USHORT
, UINT8
)
301 DEFINE_SAFE_CONVERT_UTOX(UShortToShort
, USHORT
, SHORT
)
302 DEFINE_SAFE_CONVERT_UTOX(UIntToUChar
, UINT
, UCHAR
)
303 DEFINE_SAFE_CONVERT_UTOX(UIntToInt8
, UINT
, INT8
)
304 DEFINE_SAFE_CONVERT_UTOX(UIntToUInt8
, UINT
, UINT8
)
305 DEFINE_SAFE_CONVERT_UTOX(UIntToShort
, UINT
, SHORT
)
306 DEFINE_SAFE_CONVERT_UTOX(UIntToUShort
, UINT
, USHORT
)
307 DEFINE_SAFE_CONVERT_UTOX(UIntToInt
, UINT
, INT
)
308 DEFINE_SAFE_CONVERT_UTOX(UIntToLong
, UINT
, LONG
)
309 DEFINE_SAFE_CONVERT_UTOX(UIntPtrToUChar
, UINT_PTR
, UCHAR
)
310 DEFINE_SAFE_CONVERT_UTOX(UIntPtrToInt8
, UINT_PTR
, INT8
)
311 DEFINE_SAFE_CONVERT_UTOX(UIntPtrToUInt8
, UINT_PTR
, UINT8
)
312 DEFINE_SAFE_CONVERT_UTOX(UIntPtrToShort
, UINT_PTR
, SHORT
)
313 DEFINE_SAFE_CONVERT_UTOX(UIntPtrToUShort
, UINT_PTR
, USHORT
)
314 DEFINE_SAFE_CONVERT_UTOX(UIntPtrToInt16
, UINT_PTR
, INT16
)
315 DEFINE_SAFE_CONVERT_UTOX(UIntPtrToUInt16
, UINT_PTR
, UINT16
)
316 DEFINE_SAFE_CONVERT_UTOX(UIntPtrToInt
, UINT_PTR
, INT
)
317 DEFINE_SAFE_CONVERT_UTOX(UIntPtrToLong
, UINT_PTR
, LONG
)
318 DEFINE_SAFE_CONVERT_UTOX(UIntPtrToIntPtr
, UINT_PTR
, INT_PTR
)
319 DEFINE_SAFE_CONVERT_UTOX(UIntPtrToLongPtr
, UINT_PTR
, LONG_PTR
)
320 DEFINE_SAFE_CONVERT_UTOX(ULongToUChar
, ULONG
, UCHAR
)
321 DEFINE_SAFE_CONVERT_UTOX(ULongToUInt8
, ULONG
, UINT8
)
322 DEFINE_SAFE_CONVERT_UTOX(ULongToShort
, ULONG
, SHORT
)
323 DEFINE_SAFE_CONVERT_UTOX(ULongToUShort
, ULONG
, USHORT
)
324 DEFINE_SAFE_CONVERT_UTOX(ULongToInt
, ULONG
, INT
)
325 DEFINE_SAFE_CONVERT_UTOX(ULongToUInt
, ULONG
, UINT
)
326 DEFINE_SAFE_CONVERT_UTOX(ULongToIntPtr
, ULONG
, INT_PTR
)
327 DEFINE_SAFE_CONVERT_UTOX(ULongToUIntPtr
, ULONG
, UINT_PTR
)
328 DEFINE_SAFE_CONVERT_UTOX(ULongToLongPtr
, ULONG
, LONG_PTR
)
329 DEFINE_SAFE_CONVERT_UTOX(ULongPtrToULong
, ULONG_PTR
, ULONGLONG
)
330 DEFINE_SAFE_CONVERT_UTOX(ULongLongToUInt
, ULONGLONG
, UINT
)
331 DEFINE_SAFE_CONVERT_UTOX(ULongLongToULong
, ULONGLONG
, ULONG
)
332 DEFINE_SAFE_CONVERT_UTOX(ULongLongToULongPtr
, ULONGLONG
, ULONG_PTR
)
335 #define DEFINE_SAFE_CONVERT_ITOU(_Name, _TypeFrom, _TypeTo) \
336 _Must_inspect_result_ \
339 INTSAFE_NAME(_Name)( \
340 _In_ _TypeFrom Input, \
341 _Out_ _Deref_out_range_(==, Input) _TypeTo *pOutput) \
343 if ((Input >= 0) && (Input <= _TypeTo ## _MAX)) \
345 *pOutput = (_TypeTo)Input; \
346 return INTSAFE_SUCCESS; \
350 *pOutput = _TypeTo ## _ERROR; \
351 return INTSAFE_E_ARITHMETIC_OVERFLOW; \
355 DEFINE_SAFE_CONVERT_ITOU(Int8ToUChar
, INT8
, UCHAR
)
356 DEFINE_SAFE_CONVERT_ITOU(Int8ToUInt8
, INT8
, UINT8
)
357 DEFINE_SAFE_CONVERT_ITOU(Int8ToUShort
, INT8
, USHORT
)
358 DEFINE_SAFE_CONVERT_ITOU(Int8ToUInt
, INT8
, UINT
)
359 DEFINE_SAFE_CONVERT_ITOU(Int8ToULong
, INT8
, ULONG
)
360 DEFINE_SAFE_CONVERT_ITOU(Int8ToUIntPtr
, INT8
, UINT_PTR
)
361 DEFINE_SAFE_CONVERT_ITOU(Int8ToULongPtr
, INT8
, ULONG_PTR
)
362 DEFINE_SAFE_CONVERT_ITOU(Int8ToULongLong
, INT8
, ULONGLONG
)
363 DEFINE_SAFE_CONVERT_ITOU(ShortToUChar
, SHORT
, UCHAR
)
364 DEFINE_SAFE_CONVERT_ITOU(ShortToUInt8
, SHORT
, UINT8
)
365 DEFINE_SAFE_CONVERT_ITOU(ShortToUShort
, SHORT
, USHORT
)
366 DEFINE_SAFE_CONVERT_ITOU(ShortToUInt
, SHORT
, UINT
)
367 DEFINE_SAFE_CONVERT_ITOU(ShortToULong
, SHORT
, ULONG
)
368 DEFINE_SAFE_CONVERT_ITOU(ShortToUIntPtr
, SHORT
, UINT_PTR
)
369 DEFINE_SAFE_CONVERT_ITOU(ShortToULongPtr
, SHORT
, ULONG_PTR
)
370 DEFINE_SAFE_CONVERT_ITOU(ShortToDWordPtr
, SHORT
, DWORD_PTR
)
371 DEFINE_SAFE_CONVERT_ITOU(ShortToULongLong
, SHORT
, ULONGLONG
)
372 DEFINE_SAFE_CONVERT_ITOU(IntToUChar
, INT
, UCHAR
)
373 DEFINE_SAFE_CONVERT_ITOU(IntToUInt8
, INT
, UINT8
)
374 DEFINE_SAFE_CONVERT_ITOU(IntToUShort
, INT
, USHORT
)
375 DEFINE_SAFE_CONVERT_ITOU(IntToUInt
, INT
, UINT
)
376 DEFINE_SAFE_CONVERT_ITOU(IntToULong
, INT
, ULONG
)
377 DEFINE_SAFE_CONVERT_ITOU(IntToULongLong
, INT
, ULONGLONG
)
378 DEFINE_SAFE_CONVERT_ITOU(LongToUChar
, LONG
, UCHAR
)
379 DEFINE_SAFE_CONVERT_ITOU(LongToUInt8
, LONG
, UINT8
)
380 DEFINE_SAFE_CONVERT_ITOU(LongToUShort
, LONG
, USHORT
)
381 DEFINE_SAFE_CONVERT_ITOU(LongToUInt
, LONG
, UINT
)
382 DEFINE_SAFE_CONVERT_ITOU(LongToULong
, LONG
, ULONG
)
383 DEFINE_SAFE_CONVERT_ITOU(LongToUIntPtr
, LONG
, UINT_PTR
)
384 DEFINE_SAFE_CONVERT_ITOU(LongToULongPtr
, LONG
, ULONG_PTR
)
385 DEFINE_SAFE_CONVERT_ITOU(LongToULongLong
, LONG
, ULONGLONG
)
386 DEFINE_SAFE_CONVERT_ITOU(IntPtrToUChar
, INT_PTR
, UCHAR
)
387 DEFINE_SAFE_CONVERT_ITOU(IntPtrToUInt8
, INT_PTR
, UINT8
)
388 DEFINE_SAFE_CONVERT_ITOU(IntPtrToUShort
, INT_PTR
, USHORT
)
389 DEFINE_SAFE_CONVERT_ITOU(IntPtrToUInt
, INT_PTR
, UINT
)
390 DEFINE_SAFE_CONVERT_ITOU(IntPtrToULong
, INT_PTR
, ULONG
)
391 DEFINE_SAFE_CONVERT_ITOU(IntPtrToUIntPtr
, INT_PTR
, UINT_PTR
)
392 DEFINE_SAFE_CONVERT_ITOU(IntPtrToULongPtr
, INT_PTR
, ULONG_PTR
)
393 DEFINE_SAFE_CONVERT_ITOU(IntPtrToULongLong
, INT_PTR
, ULONGLONG
)
394 DEFINE_SAFE_CONVERT_ITOU(LongPtrToUChar
, LONG_PTR
, UCHAR
)
395 DEFINE_SAFE_CONVERT_ITOU(LongPtrToUInt8
, LONG_PTR
, UINT8
)
396 DEFINE_SAFE_CONVERT_ITOU(LongPtrToUShort
, LONG_PTR
, USHORT
)
397 DEFINE_SAFE_CONVERT_ITOU(LongPtrToUInt
, LONG_PTR
, UINT
)
398 DEFINE_SAFE_CONVERT_ITOU(LongPtrToULong
, LONG_PTR
, ULONG
)
399 DEFINE_SAFE_CONVERT_ITOU(LongPtrToUIntPtr
, LONG_PTR
, UINT_PTR
)
400 DEFINE_SAFE_CONVERT_ITOU(LongPtrToULongPtr
, LONG_PTR
, ULONG_PTR
)
401 DEFINE_SAFE_CONVERT_ITOU(LongPtrToULongLong
, LONG_PTR
, ULONGLONG
)
402 #ifdef _CHAR_UNSIGNED
403 DEFINE_SAFE_CONVERT_ITOU(ShortToChar
, SHORT
, UCHAR
)
404 DEFINE_SAFE_CONVERT_ITOU(LongPtrToChar
, LONG_PTR
, UCHAR
)
408 #define DEFINE_SAFE_CONVERT_ITOI(_Name, _TypeFrom, _TypeTo) \
409 _Must_inspect_result_ \
412 INTSAFE_NAME(_Name)( \
413 _In_ _TypeFrom Input, \
414 _Out_ _Deref_out_range_(==, Input) _TypeTo *pOutput) \
416 if ((Input >= _TypeTo ## _MIN) && (Input <= _TypeTo ## _MAX)) \
418 *pOutput = (_TypeTo)Input; \
419 return INTSAFE_SUCCESS; \
423 *pOutput = _TypeTo ## _ERROR; \
424 return INTSAFE_E_ARITHMETIC_OVERFLOW; \
428 DEFINE_SAFE_CONVERT_ITOI(ShortToInt8
, SHORT
, INT8
)
429 DEFINE_SAFE_CONVERT_ITOI(IntToInt8
, INT
, INT8
)
430 DEFINE_SAFE_CONVERT_ITOI(IntToShort
, INT
, SHORT
)
431 DEFINE_SAFE_CONVERT_ITOI(LongToInt8
, LONG
, INT8
)
432 DEFINE_SAFE_CONVERT_ITOI(LongToShort
, LONG
, SHORT
)
433 DEFINE_SAFE_CONVERT_ITOI(LongToInt
, LONG
, INT
)
434 DEFINE_SAFE_CONVERT_ITOI(IntPtrToInt8
, INT_PTR
, INT8
)
435 DEFINE_SAFE_CONVERT_ITOI(IntPtrToShort
, INT_PTR
, SHORT
)
436 DEFINE_SAFE_CONVERT_ITOI(IntPtrToInt
, INT_PTR
, INT
)
437 DEFINE_SAFE_CONVERT_ITOI(IntPtrToLong
, INT_PTR
, LONG
)
438 DEFINE_SAFE_CONVERT_ITOI(IntPtrToLongPtr
, INT_PTR
, LONG_PTR
)
439 DEFINE_SAFE_CONVERT_ITOI(LongPtrToInt8
, LONG_PTR
, INT8
)
440 DEFINE_SAFE_CONVERT_ITOI(LongPtrToShort
, LONG_PTR
, SHORT
)
441 DEFINE_SAFE_CONVERT_ITOI(LongPtrToInt
, LONG_PTR
, INT
)
442 DEFINE_SAFE_CONVERT_ITOI(LongPtrToLong
, LONG_PTR
, LONG
)
443 DEFINE_SAFE_CONVERT_ITOI(LongPtrToIntPtr
, LONG_PTR
, INT_PTR
)
444 DEFINE_SAFE_CONVERT_ITOI(LongLongToLong
, LONGLONG
, LONG
)
445 DEFINE_SAFE_CONVERT_ITOI(LongLongToIntPtr
, LONGLONG
, INT_PTR
)
446 DEFINE_SAFE_CONVERT_ITOI(LongLongToLongPtr
, LONGLONG
, LONG_PTR
)
447 #ifndef _CHAR_UNSIGNED
448 DEFINE_SAFE_CONVERT_ITOI(ShortToChar
, SHORT
, CHAR
)
449 DEFINE_SAFE_CONVERT_ITOI(LongPtrToChar
, LONG_PTR
, CHAR
)
453 #ifdef _NTINTSAFE_H_INCLUDED_
455 #define RtlInt8ToByte RtlInt8ToUInt8
456 #define RtlInt8ToUInt16 RtlInt8ToUShort
457 #define RtlInt8ToWord RtlInt8ToUShort
458 #define RtlInt8ToUInt32 RtlInt8ToUInt
459 #define RtlInt8ToDWord RtlInt8ToULong
460 #define RtlInt8ToDWordPtr RtlInt8ToULongPtr
461 #define RtlInt8ToDWordLong RtlInt8ToULongLong
462 #define RtlInt8ToULong64 RtlInt8ToULongLong
463 #define RtlInt8ToDWord64 RtlInt8ToULongLong
464 #define RtlInt8ToUInt64 RtlInt8ToULongLong
465 #define RtlInt8ToSizeT RtlInt8ToUIntPtr
466 #define RtlInt8ToSIZET RtlInt8ToULongPtr
467 #define RtlIntToSizeT RtlIntToUIntPtr
468 #define RtlIntToSIZET RtlIntToULongPtr
469 #define RtlULongToByte RtlULongToUInt8
470 #define RtlULongLongToInt64 RtlULongLongToLongLong
471 #define RtlULongLongToLong64 RtlULongLongToLongLong
472 #define RtlULongLongToPtrdiffT RtlULongLongToIntPtr
473 #define RtlULongLongToSizeT RtlULongLongToUIntPtr
474 #define RtlULongLongToSSIZET RtlULongLongToLongPtr
475 #define RtlULongLongToSIZET RtlULongLongToULongPtr
476 #define RtlSIZETToULong RtlULongPtrToULong
477 #define RtlSSIZETToULongLong RtlLongPtrToULongLong
478 #define RtlSSIZETToULong RtlLongPtrToULong
480 #define RtlIntToUIntPtr RtlIntToULongLong
481 #define RtlULongLongToIntPtr RtlULongLongToLongLong
483 #define RtlIntToUIntPtr RtlIntToUInt
484 #define RtlULongLongToIntPtr RtlULongLongToInt
485 #define RtlULongLongToUIntPtr RtlULongLongToUInt
486 #define RtlULongLongToULongPtr RtlULongLongToULong
489 #else // _NTINTSAFE_H_INCLUDED_
491 #define Int8ToByte Int8ToUInt8
492 #define Int8ToUInt16 Int8ToUShort
493 #define Int8ToWord Int8ToUShort
494 #define Int8ToUInt32 Int8ToUInt
495 #define Int8ToDWord Int8ToULong
496 #define Int8ToDWordPtr Int8ToULongPtr
497 #define Int8ToDWordLong Int8ToULongLong
498 #define Int8ToULong64 Int8ToULongLong
499 #define Int8ToDWord64 Int8ToULongLong
500 #define Int8ToUInt64 Int8ToULongLong
501 #define Int8ToSizeT Int8ToUIntPtr
502 #define Int8ToSIZET Int8ToULongPtr
503 #define IntToSizeT IntToUIntPtr
504 #define IntToSIZET IntToULongPtr
505 #define ULongToByte ULongToUInt8
506 #define ULongLongToInt64 ULongLongToLongLong
507 #define ULongLongToLong64 ULongLongToLongLong
508 #define ULongLongToPtrdiffT ULongLongToIntPtr
509 #define ULongLongToSizeT ULongLongToUIntPtr
510 #define ULongLongToSSIZET ULongLongToLongPtr
511 #define ULongLongToSIZET ULongLongToULongPtr
512 #define SIZETToULong ULongPtrToULong
513 #define SSIZETToULongLong LongPtrToULongLong
514 #define SSIZETToULong LongPtrToULong
516 #define IntToUIntPtr IntToULongLong
517 #define ULongLongToIntPtr ULongLongToLongLong
519 #define IntToUIntPtr IntToUInt
520 #define ULongLongToIntPtr ULongLongToInt
521 #define ULongLongToUIntPtr ULongLongToUInt
522 #define ULongLongToULongPtr ULongLongToULong
525 #endif // _NTINTSAFE_H_INCLUDED_
528 #define DEFINE_SAFE_ADD(_Name, _Type) \
529 _Must_inspect_result_ \
532 INTSAFE_NAME(_Name)( \
535 _Out_ _Deref_out_range_(==, Augend + Addend) _Type *pOutput) \
537 if ((Augend + Addend) >= Augend) \
539 *pOutput = Augend + Addend; \
540 return INTSAFE_SUCCESS; \
544 *pOutput = _Type ## _ERROR; \
545 return INTSAFE_E_ARITHMETIC_OVERFLOW; \
549 DEFINE_SAFE_ADD(UInt8Add
, UINT8
)
550 DEFINE_SAFE_ADD(UShortAdd
, USHORT
)
551 DEFINE_SAFE_ADD(UIntAdd
, UINT
)
552 DEFINE_SAFE_ADD(ULongAdd
, ULONG
)
553 DEFINE_SAFE_ADD(UIntPtrAdd
, UINT_PTR
)
554 DEFINE_SAFE_ADD(ULongPtrAdd
, ULONG_PTR
)
555 DEFINE_SAFE_ADD(DWordPtrAdd
, DWORD_PTR
)
556 DEFINE_SAFE_ADD(SizeTAdd
, size_t)
557 DEFINE_SAFE_ADD(SIZETAdd
, SIZE_T
)
558 DEFINE_SAFE_ADD(ULongLongAdd
, ULONGLONG
)
561 #define DEFINE_SAFE_SUB(_Name, _Type) \
562 _Must_inspect_result_ \
565 INTSAFE_NAME(_Name)( \
566 _In_ _Type Minuend, \
567 _In_ _Type Subtrahend, \
568 _Out_ _Deref_out_range_(==, Minuend - Subtrahend) _Type* pOutput) \
570 if (Minuend >= Subtrahend) \
572 *pOutput = Minuend - Subtrahend; \
573 return INTSAFE_SUCCESS; \
577 *pOutput = _Type ## _ERROR; \
578 return INTSAFE_E_ARITHMETIC_OVERFLOW; \
582 DEFINE_SAFE_SUB(UInt8Sub
, UINT8
)
583 DEFINE_SAFE_SUB(UShortSub
, USHORT
)
584 DEFINE_SAFE_SUB(UIntSub
, UINT
)
585 DEFINE_SAFE_SUB(UIntPtrSub
, UINT_PTR
)
586 DEFINE_SAFE_SUB(ULongSub
, ULONG
)
587 DEFINE_SAFE_SUB(ULongPtrSub
, ULONG_PTR
)
588 DEFINE_SAFE_SUB(DWordPtrSub
, DWORD_PTR
)
589 DEFINE_SAFE_SUB(SizeTSub
, size_t)
590 DEFINE_SAFE_SUB(SIZETSub
, SIZE_T
)
591 DEFINE_SAFE_SUB(ULongLongSub
, ULONGLONG
)
594 _Must_inspect_result_
597 INTSAFE_NAME(LongLongSub
)(
598 _In_ LONGLONG Minuend
,
599 _In_ LONGLONG Subtrahend
,
600 _Out_
_Deref_out_range_(==, Minuend
- Subtrahend
) LONGLONG
* pResult
)
602 LONGLONG Result
= Minuend
- Subtrahend
;
604 /* The only way the result can overflow, is when the sign of the minuend
605 and the subtrahend differ. In that case the result is expected to
606 have the same sign as the minuend, otherwise it overflowed.
607 Sign equality is checked with a binary xor operation. */
608 if ( ((Minuend
^ Subtrahend
) < 0) && ((Minuend
^ Result
) < 0) )
610 *pResult
= LONGLONG_ERROR
;
611 return INTSAFE_E_ARITHMETIC_OVERFLOW
;
616 return INTSAFE_SUCCESS
;
621 #define DEFINE_SAFE_SUB_S(_Name, _Type1, _Type2, _Convert) \
622 _Must_inspect_result_ \
625 INTSAFE_NAME(_Name)( \
626 _In_ _Type1 Minuend, \
627 _In_ _Type1 Subtrahend, \
628 _Out_ _Deref_out_range_(==, Minuend - Subtrahend) _Type1* pOutput) \
630 return INTSAFE_NAME(_Convert)(((_Type2)Minuend) - ((_Type2)Subtrahend), pOutput); \
633 DEFINE_SAFE_SUB_S(LongSub
, LONG
, LONGLONG
, LongLongToLong
)
635 DEFINE_SAFE_SUB_S(IntPtrSub
, INT_PTR
, LONGLONG
, LongLongToIntPtr
)
636 DEFINE_SAFE_SUB_S(LongPtrSub
, LONG_PTR
, LONGLONG
, LongLongToLongPtr
)
640 _Must_inspect_result_
643 INTSAFE_NAME(ULongLongMult
)(
644 _In_ ULONGLONG Multiplicand
,
645 _In_ ULONGLONG Multiplier
,
646 _Out_
_Deref_out_range_(==, Multiplicand
* Multiplier
) ULONGLONG
* pOutput
)
648 /* We can split the 64 bit numbers in low and high parts:
649 M1 = M1Low + M1Hi * 0x100000000
650 M2 = M2Low + M2Hi * 0x100000000
652 Then the multiplication looks like this:
653 M1 * M2 = (M1Low + M1Hi * 0x100000000) + (M2Low + M2Hi * 0x100000000)
655 + M1Low * M2Hi * 0x100000000
656 + M2Low * M1Hi * 0x100000000
657 + M1Hi * M2Hi * 0x100000000 * 0x100000000
659 We get an overflow when
660 a) M1Hi * M2Hi != 0, so when M1Hi or M2Hi are not 0
661 b) The product of the nonzero high part and the other low part
662 is larger than 32 bits.
663 c) The addition of the product from b) shifted left by 32 and
664 M1Low * M2Low is larger than 64 bits
666 ULONG M1Low
= Multiplicand
& 0xffffffff;
667 ULONG M2Low
= Multiplier
& 0xffffffff;
668 ULONG M1Hi
= Multiplicand
>> 32;
669 ULONG M2Hi
= Multiplier
>> 32;
674 Temp
= UInt32x32To64(M1Low
, M2Hi
);
678 Temp
= UInt32x32To64(M1Hi
, M2Low
);
682 *pOutput
= LONGLONG_ERROR
;
683 return INTSAFE_E_ARITHMETIC_OVERFLOW
;
686 if (Temp
> ULONG_MAX
)
688 *pOutput
= LONGLONG_ERROR
;
689 return INTSAFE_E_ARITHMETIC_OVERFLOW
;
692 return INTSAFE_NAME(ULongLongAdd
)(Temp
<< 32, UInt32x32To64(M1Low
, M2Low
), pOutput
);
696 #define DEFINE_SAFE_MULT_U32(_Name, _Type, _Convert) \
700 INTSAFE_NAME(_Name)( \
701 _In_ _Type Multiplicand, \
702 _In_ _Type Multiplier, \
703 _Out_ _Deref_out_range_(==, Multiplicand * Multiplier) _Type* pOutput) \
705 ULONGLONG Result = UInt32x32To64(Multiplicand, Multiplier); \
706 return INTSAFE_NAME(_Convert)(Result, pOutput); \
709 DEFINE_SAFE_MULT_U32(ULongMult
, ULONG
, ULongLongToULong
)
711 DEFINE_SAFE_MULT_U32(SizeTMult
, size_t, ULongLongToSizeT
)
712 DEFINE_SAFE_MULT_U32(SIZETMult
, SIZE_T
, ULongLongToSIZET
)
716 #ifdef _NTINTSAFE_H_INCLUDED_
718 #define RtlUInt16Add RtlUShortAdd
719 #define RtlWordAdd RtlUShortAdd
720 #define RtlUInt32Add RtlUIntAdd
721 #define RtlDWordAdd RtlULongAdd
722 #define RtlDWordLongAdd RtlULongLongAdd
723 #define RtlULong64Add RtlULongLongAdd
724 #define RtlDWord64Add RtlULongLongAdd
725 #define RtlUInt64Add RtlULongLongAdd
726 #define RtlUInt16Sub RtlUShortSub
727 #define RtlWordSub RtlUShortSub
728 #define RtlUInt32Sub RtlUIntSub
729 #define RtlDWordSub RtlULongSub
730 #define RtlDWordLongSub RtlULongLongSub
731 #define RtlULong64Sub RtlULongLongSub
732 #define RtlDWord64Sub RtlULongLongSub
733 #define RtlUInt64Sub RtlULongLongSub
735 #define RtlIntPtrSub RtlLongLongSub
736 #define RtlLongPtrSub RtlLongLongSub
737 #define RtlSizeTMult RtlULongLongMult
738 #define RtlSIZETMult RtlULongLongMult
742 #else // _NTINTSAFE_H_INCLUDED_
744 #define UInt16Add UShortAdd
745 #define WordAdd UShortAdd
746 #define UInt32Add UIntAdd
747 #define DWordAdd ULongAdd
748 #define DWordLongAdd ULongLongAdd
749 #define ULong64Add ULongLongAdd
750 #define DWord64Add ULongLongAdd
751 #define UInt64Add ULongLongAdd
752 #define UInt16Sub UShortSub
753 #define WordSub UShortSub
754 #define UInt32Sub UIntSub
755 #define DWordSub ULongSub
756 #define DWordLongSub ULongLongSub
757 #define ULong64Sub ULongLongSub
758 #define DWord64Sub ULongLongSub
759 #define UInt64Sub ULongLongSub
761 #define IntPtrSub LongLongSub
762 #define LongPtrSub LongLongSub
763 #define SizeTMult ULongLongMult
764 #define SIZETMult ULongLongMult
768 #endif // _NTINTSAFE_H_INCLUDED_
770 #endif // !_INTSAFE_H_INCLUDED_