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