ReactOS 0.4.15-dev-7788-g1ad9096
intsafe.h
Go to the documentation of this file.
1
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 */
36typedef _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
47typedef _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_
80typedef char CHAR;
81typedef unsigned char UCHAR, UINT8;
82typedef signed char INT8;
83typedef short SHORT;
84typedef signed short INT16;
85typedef unsigned short USHORT, UINT16;
86typedef int INT;
87typedef unsigned int UINT32;
88typedef signed int INT32;
89typedef long LONG;
90typedef unsigned long ULONG;
91typedef long long LONGLONG, LONG64;
92typedef signed long long INT64;
93typedef unsigned long long ULONGLONG, DWORDLONG, ULONG64, DWORD64, UINT64;
94#ifdef _WIN64
95typedef long long INT_PTR, LONG_PTR, SSIZE_T, ptrdiff_t;
96typedef unsigned long long UINT_PTR, ULONG_PTR, DWORD_PTR, SIZE_T, size_t;
97#else // _WIN64
98typedef _W64 int INT_PTR, ptrdiff_t;
99typedef _W64 unsigned int UINT_PTR, size_t;
100typedef _W64 long LONG_PTR, SSIZE_T;
101typedef _W64 unsigned long ULONG_PTR, DWORD_PTR, SIZE_T;
102#endif // _WIN64
103#endif
104typedef unsigned char BYTE;
105typedef unsigned short WORD;
106typedef unsigned int UINT;
107typedef unsigned long DWORD;
108#endif // _WINNT_
109
110/* Just to be sure! */
111C_ASSERT(sizeof(USHORT) == 2);
112C_ASSERT(sizeof(INT) == 4);
113C_ASSERT(sizeof(UINT) == 4);
114C_ASSERT(sizeof(LONG) == 4);
115C_ASSERT(sizeof(ULONG) == 4);
116C_ASSERT(sizeof(DWORD) == 4);
117C_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 \
259INTSAFE_RESULT \
260INTSAFE_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
313DEFINE_SAFE_CONVERT_UTOX(ULongLongToUInt, ULONGLONG, UINT)
314DEFINE_SAFE_CONVERT_UTOX(ULongLongToULong, ULONGLONG, ULONG)
316
317
318/* Convert signed to unsigned */
319#define DEFINE_SAFE_CONVERT_STOU(_Name, _TypeFrom, _TypeTo) \
320_Must_inspect_result_ \
321__forceinline \
322INTSAFE_RESULT \
323INTSAFE_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
347DEFINE_SAFE_CONVERT_STOU(Int8ToULongLong, INT8, ULONGLONG)
356DEFINE_SAFE_CONVERT_STOU(ShortToULongLong, SHORT, ULONGLONG)
362DEFINE_SAFE_CONVERT_STOU(IntToULongLong, INT, ULONGLONG)
370DEFINE_SAFE_CONVERT_STOU(LongToULongLong, LONG, ULONGLONG)
378DEFINE_SAFE_CONVERT_STOU(IntPtrToULongLong, INT_PTR, ULONGLONG)
386DEFINE_SAFE_CONVERT_STOU(LongPtrToULongLong, LONG_PTR, ULONGLONG)
387DEFINE_SAFE_CONVERT_STOU(LongLongToULong, LONGLONG, ULONG)
388DEFINE_SAFE_CONVERT_STOU(LongLongToULongPtr, LONGLONG, ULONG_PTR)
389#ifdef _CHAR_UNSIGNED
392#endif
393
394
395/* Convert signed to signed */
396#define DEFINE_SAFE_CONVERT_STOS(_Name, _TypeFrom, _TypeTo) \
397_Must_inspect_result_ \
398__forceinline \
399INTSAFE_RESULT \
400INTSAFE_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
433DEFINE_SAFE_CONVERT_STOS(LongLongToLong, LONGLONG, LONG)
434DEFINE_SAFE_CONVERT_STOS(LongLongToIntPtr, LONGLONG, INT_PTR)
435DEFINE_SAFE_CONVERT_STOS(LongLongToLongPtr, LONGLONG, LONG_PTR)
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 \
526INTSAFE_RESULT \
527INTSAFE_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
544DEFINE_SAFE_ADD(UInt8Add, UINT8)
545DEFINE_SAFE_ADD(UShortAdd, USHORT)
546DEFINE_SAFE_ADD(UIntAdd, UINT)
547DEFINE_SAFE_ADD(ULongAdd, ULONG)
548DEFINE_SAFE_ADD(UIntPtrAdd, UINT_PTR)
549DEFINE_SAFE_ADD(ULongPtrAdd, ULONG_PTR)
550DEFINE_SAFE_ADD(DWordPtrAdd, DWORD_PTR)
551DEFINE_SAFE_ADD(SizeTAdd, size_t)
552DEFINE_SAFE_ADD(SIZETAdd, SIZE_T)
553DEFINE_SAFE_ADD(ULongLongAdd, ULONGLONG)
554
555
556#define DEFINE_SAFE_SUB(_Name, _Type) \
557_Must_inspect_result_ \
558__forceinline \
559INTSAFE_RESULT \
560INTSAFE_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
577DEFINE_SAFE_SUB(UInt8Sub, UINT8)
578DEFINE_SAFE_SUB(UShortSub, USHORT)
579DEFINE_SAFE_SUB(UIntSub, UINT)
580DEFINE_SAFE_SUB(UIntPtrSub, UINT_PTR)
581DEFINE_SAFE_SUB(ULongSub, ULONG)
582DEFINE_SAFE_SUB(ULongPtrSub, ULONG_PTR)
583DEFINE_SAFE_SUB(DWordPtrSub, DWORD_PTR)
584DEFINE_SAFE_SUB(SizeTSub, size_t)
585DEFINE_SAFE_SUB(SIZETSub, SIZE_T)
586DEFINE_SAFE_SUB(ULongLongSub, ULONGLONG)
587
588#ifdef ENABLE_INTSAFE_SIGNED_FUNCTIONS
590__forceinline
592INTSAFE_NAME(LongLongAdd)(
593 _In_ LONGLONG Augend,
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;
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) \
617C_ASSERT(sizeof(_Type2) > sizeof(_Type1)); \
618_Must_inspect_result_ \
619__forceinline \
620INTSAFE_RESULT \
621INTSAFE_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
629DEFINE_SAFE_ADD_S(Int8Add, INT8, SHORT, ShortToInt8)
630DEFINE_SAFE_ADD_S(ShortAdd, SHORT, INT, IntToShort)
631DEFINE_SAFE_ADD_S(IntAdd, INT, LONGLONG, LongLongToInt)
632DEFINE_SAFE_ADD_S(LongAdd, LONG, LONGLONG, LongLongToLong)
633#ifndef _WIN64
634DEFINE_SAFE_ADD_S(IntPtrAdd, INT_PTR, LONGLONG, LongLongToIntPtr)
635DEFINE_SAFE_ADD_S(LongPtrAdd, LONG_PTR, LONGLONG, LongLongToLongPtr)
636#endif
637
639__forceinline
641INTSAFE_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;
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) \
666C_ASSERT(sizeof(_Type2) > sizeof(_Type1)); \
667_Must_inspect_result_ \
668__forceinline \
669INTSAFE_RESULT \
670INTSAFE_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
678DEFINE_SAFE_SUB_S(LongSub, LONG, LONGLONG, LongLongToLong)
679#ifndef _WIN64
680DEFINE_SAFE_SUB_S(IntPtrSub, INT_PTR, LONGLONG, LongLongToIntPtr)
681DEFINE_SAFE_SUB_S(LongPtrSub, LONG_PTR, LONGLONG, LongLongToLongPtr)
682#endif
683
684#endif /* ENABLE_INTSAFE_SIGNED_FUNCTIONS */
685
687__forceinline
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;
730 }
731
732 if (Temp > ULONG_MAX)
733 {
734 *pOutput = ULONGLONG_ERROR;
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 \
745INTSAFE_RESULT \
746INTSAFE_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
755DEFINE_SAFE_MULT_U32(ULongMult, ULONG, ULongLongToULong)
756#ifndef _WIN64
757DEFINE_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 \
764INTSAFE_RESULT \
765INTSAFE_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
774DEFINE_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_
unsigned short UINT16
signed short INT16
signed char INT8
unsigned char UINT8
LONG NTSTATUS
Definition: precomp.h:26
unsigned long
Definition: typeof.h:102
IN OUT PLONG Addend
Definition: CrNtStubs.h:25
unsigned long DWORD
Definition: ntddk_ex.h:95
unsigned short UINT16
Definition: intsafe.h:85
signed int INT32
Definition: intsafe.h:88
unsigned short WORD
Definition: intsafe.h:105
#define INTSAFE_SUCCESS
Definition: intsafe.h:55
_W64 unsigned int size_t
Definition: intsafe.h:99
#define INTSAFE_RESULT
Definition: intsafe.h:54
#define ULONGLONG_ERROR
Definition: intsafe.h:209
unsigned long long ULONG64
Definition: intsafe.h:93
#define DEFINE_SAFE_MULT_U32(_Name, _Type, _Convert)
Definition: intsafe.h:742
_W64 int ptrdiff_t
Definition: intsafe.h:98
#define ULongLongToULongPtr
Definition: intsafe.h:517
long LONG
Definition: intsafe.h:89
signed short INT16
Definition: intsafe.h:84
unsigned int UINT
Definition: intsafe.h:106
#define _W64
Definition: intsafe.h:64
int INT
Definition: intsafe.h:86
#define ULONG_MAX
Definition: intsafe.h:155
#define DEFINE_SAFE_CONVERT_STOU(_Name, _TypeFrom, _TypeTo)
Definition: intsafe.h:319
#define UInt32x32To64(a, b)
Definition: intsafe.h:252
#define DEFINE_SAFE_CONVERT_STOS(_Name, _TypeFrom, _TypeTo)
Definition: intsafe.h:396
unsigned char BYTE
Definition: intsafe.h:104
#define DEFINE_SAFE_MULT_U16(_Name, _Type, _Convert)
Definition: intsafe.h:761
unsigned char UCHAR
Definition: intsafe.h:81
_W64 unsigned int UINT_PTR
Definition: intsafe.h:99
unsigned long long UINT64
Definition: intsafe.h:93
unsigned short USHORT
Definition: intsafe.h:85
#define INTSAFE_E_ARITHMETIC_OVERFLOW
Definition: intsafe.h:56
_W64 unsigned long DWORD_PTR
Definition: intsafe.h:101
#define _INTSAFE_CHAR
Definition: intsafe.h:236
unsigned long long DWORDLONG
Definition: intsafe.h:93
#define DEFINE_SAFE_CONVERT_UTOX(_Name, _TypeFrom, _TypeTo)
Definition: intsafe.h:256
signed char INT8
Definition: intsafe.h:82
#define ULongLongToSIZET
Definition: intsafe.h:503
_Must_inspect_result_ __forceinline INTSAFE_RESULT INTSAFE_NAME() ULongLongMult(_In_ ULONGLONG Multiplicand, _In_ ULONGLONG Multiplier, _Out_ _Deref_out_range_(==, Multiplicand *Multiplier) ULONGLONG *pOutput)
Definition: intsafe.h:689
#define INTSAFE_NAME(name)
Definition: intsafe.h:57
#define DEFINE_SAFE_SUB(_Name, _Type)
Definition: intsafe.h:556
short SHORT
Definition: intsafe.h:83
#define DEFINE_SAFE_ADD(_Name, _Type)
Definition: intsafe.h:523
_W64 int INT_PTR
Definition: intsafe.h:98
#define ULongLongToSizeT
Definition: intsafe.h:501
unsigned char UINT8
Definition: intsafe.h:81
_W64 long LONG_PTR
Definition: intsafe.h:100
unsigned long long ULONGLONG
Definition: intsafe.h:93
_W64 unsigned long ULONG_PTR
Definition: intsafe.h:101
#define C_ASSERT(e)
Definition: intsafe.h:73
_W64 long SSIZE_T
Definition: intsafe.h:100
unsigned long DWORD
Definition: intsafe.h:107
#define LONGLONG_ERROR
Definition: intsafe.h:206
_W64 unsigned long SIZE_T
Definition: intsafe.h:101
unsigned long long DWORD64
Definition: intsafe.h:93
unsigned int UINT32
Definition: intsafe.h:87
long long LONG64
Definition: intsafe.h:91
char CHAR
Definition: intsafe.h:80
signed long long INT64
Definition: intsafe.h:92
long long LONGLONG
Definition: intsafe.h:91
unsigned long ULONG
Definition: intsafe.h:90
#define _Deref_out_range_(lb, ub)
Definition: ms_sal.h:575
#define _Return_type_success_(expr)
Definition: ms_sal.h:263
#define _Must_inspect_result_
Definition: ms_sal.h:558
#define _Out_
Definition: ms_sal.h:345
#define _In_
Definition: ms_sal.h:308
__int3264 LONG_PTR
Definition: mstsclib_h.h:276
unsigned __int3264 UINT_PTR
Definition: mstsclib_h.h:274
unsigned int UINT
Definition: ndis.h:50
short SHORT
Definition: pedump.c:59
long LONG
Definition: pedump.c:60
unsigned short USHORT
Definition: pedump.c:61
int32_t INT_PTR
Definition: typedefs.h:64
uint32_t DWORD_PTR
Definition: typedefs.h:65
int64_t LONGLONG
Definition: typedefs.h:68
ULONG_PTR SIZE_T
Definition: typedefs.h:80
int32_t INT
Definition: typedefs.h:58
uint32_t ULONG_PTR
Definition: typedefs.h:65
uint32_t ULONG
Definition: typedefs.h:59
uint64_t ULONGLONG
Definition: typedefs.h:67
_At_(*)(_In_ PWSK_CLIENT Client, _In_opt_ PUNICODE_STRING NodeName, _In_opt_ PUNICODE_STRING ServiceName, _In_opt_ ULONG NameSpace, _In_opt_ GUID *Provider, _In_opt_ PADDRINFOEXW Hints, _Outptr_ PADDRINFOEXW *Result, _In_opt_ PEPROCESS OwningProcess, _In_opt_ PETHREAD OwningThread, _Inout_ PIRP Irp Result)(Mem)) NTSTATUS(WSKAPI *PFN_WSK_GET_ADDRESS_INFO
Definition: wsk.h:409
unsigned char BYTE
Definition: xxhash.c:193