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