mirror of
https://github.com/reactos/reactos.git
synced 2024-10-30 03:27:31 +00:00
ddb3d908c9
svn path=/branches/shell-experiments/; revision=62286
797 lines
25 KiB
C
797 lines
25 KiB
C
/*!
|
|
* \file intsafe.h
|
|
*
|
|
* \brief Windows helper functions for integer overflow prevention
|
|
*
|
|
* \package This file is part of the ReactOS PSDK package.
|
|
*
|
|
* \author
|
|
* Timo Kreuzer (timo.kreuzer@reactos.org)
|
|
*
|
|
* \copyright THIS SOFTWARE IS NOT COPYRIGHTED
|
|
*
|
|
* This source code is offered for use in the public domain. You may
|
|
* use, modify or distribute it freely.
|
|
*
|
|
* This code is distributed in the hope that it will be useful but
|
|
* WITHOUT ANY WARRANTY. ALL WARRANTIES, EXPRESS OR IMPLIED ARE HEREBY
|
|
* DISCLAIMED. This includes but is not limited to warranties of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
*
|
|
* \todo
|
|
* - missing conversion functions
|
|
* - multiplication functions
|
|
* - signed add, sub and multiply functions
|
|
*/
|
|
#pragma once
|
|
|
|
#ifndef _INTSAFE_H_INCLUDED_
|
|
#define _INTSAFE_H_INCLUDED_
|
|
|
|
#include <specstrings.h>
|
|
|
|
#if defined(__GNUC__) && !defined(__forceinline)
|
|
# if ( __MINGW_GNUC_PREREQ(4, 3) && __STDC_VERSION__ >= 199901L)
|
|
# define __forceinline extern inline __attribute__((__always_inline__,__gnu_inline__))
|
|
# else
|
|
# define __forceinline extern __inline__ __attribute__((__always_inline__))
|
|
# endif
|
|
#endif
|
|
|
|
/* Handle ntintsafe here too */
|
|
#ifdef _NTINTSAFE_H_INCLUDED_
|
|
#ifndef _NTDEF_ /* Guard agains redefinition from ntstatus.h */
|
|
typedef _Return_type_success_(return >= 0) long NTSTATUS;
|
|
#endif
|
|
#define NT_SUCCESS(Status) (((NTSTATUS)(Status)) >= 0)
|
|
#define STATUS_SUCCESS ((NTSTATUS)0x00000000)
|
|
#define STATUS_INTEGER_OVERFLOW ((NTSTATUS)0xC0000095)
|
|
#define INTSAFE_RESULT NTSTATUS
|
|
#define INTSAFE_SUCCESS STATUS_SUCCESS
|
|
#define INTSAFE_E_ARITHMETIC_OVERFLOW STATUS_INTEGER_OVERFLOW
|
|
#define INTSAFE_NAME(name) Rtl##name
|
|
#else // _NTINTSAFE_H_INCLUDED_
|
|
#ifndef _HRESULT_DEFINED
|
|
typedef _Return_type_success_(return >= 0) long HRESULT;
|
|
#endif
|
|
#define SUCCEEDED(hr) (((HRESULT)(hr)) >= 0)
|
|
#define FAILED(hr) (((HRESULT)(hr)) < 0)
|
|
#define S_OK ((HRESULT)0L)
|
|
#define INTSAFE_RESULT HRESULT
|
|
#define INTSAFE_SUCCESS S_OK
|
|
#define INTSAFE_E_ARITHMETIC_OVERFLOW ((HRESULT)0x80070216L)
|
|
#define INTSAFE_NAME(name) name
|
|
#endif // _NTINTSAFE_H_INCLUDED_
|
|
|
|
#if !defined(_W64)
|
|
#if defined(_MSC_VER) && !defined(__midl) && (defined(_M_IX86) || defined(_M_ARM))
|
|
#define _W64 __w64
|
|
#else
|
|
#define _W64
|
|
#endif
|
|
#endif
|
|
|
|
/* Static assert */
|
|
#ifndef C_ASSERT
|
|
#ifdef _MSC_VER
|
|
# define C_ASSERT(e) typedef char __C_ASSERT__[(e)?1:-1]
|
|
#else
|
|
# define C_ASSERT(e) extern void __C_ASSERT__(int [(e)?1:-1])
|
|
#endif
|
|
#endif /* C_ASSERT */
|
|
|
|
/* Typedefs */
|
|
#ifndef _WINNT_
|
|
#ifndef _NTDEF_
|
|
typedef char CHAR;
|
|
typedef unsigned char UCHAR, UINT8;
|
|
typedef signed char INT8;
|
|
typedef short SHORT;
|
|
typedef signed short INT16;
|
|
typedef unsigned short USHORT, UINT16;
|
|
typedef int INT;
|
|
typedef unsigned int UINT32;
|
|
typedef signed int INT32;
|
|
typedef long LONG;
|
|
typedef unsigned long ULONG;
|
|
typedef long long LONGLONG, LONG64;
|
|
typedef signed long long INT64;
|
|
typedef unsigned long long ULONGLONG, DWORDLONG, ULONG64, DWORD64, UINT64;
|
|
#ifdef _WIN64
|
|
typedef long long INT_PTR, LONG_PTR, SSIZE_T, ptrdiff_t;
|
|
typedef unsigned long long UINT_PTR, ULONG_PTR, DWORD_PTR, SIZE_T, size_t;
|
|
#else // _WIN64
|
|
typedef _W64 int INT_PTR, ptrdiff_t;
|
|
typedef _W64 unsigned int UINT_PTR, size_t;
|
|
typedef _W64 long LONG_PTR, SSIZE_T;
|
|
typedef _W64 unsigned long ULONG_PTR, DWORD_PTR, SIZE_T;
|
|
#endif // _WIN64
|
|
#endif
|
|
typedef unsigned char BYTE;
|
|
typedef unsigned short WORD;
|
|
typedef unsigned int UINT;
|
|
typedef unsigned long DWORD;
|
|
#endif // _WINNT_
|
|
|
|
/* Just to be sure! */
|
|
C_ASSERT(sizeof(USHORT) == 2);
|
|
C_ASSERT(sizeof(INT) == 4);
|
|
C_ASSERT(sizeof(UINT) == 4);
|
|
C_ASSERT(sizeof(LONG) == 4);
|
|
C_ASSERT(sizeof(ULONG) == 4);
|
|
C_ASSERT(sizeof(DWORD) == 4);
|
|
C_ASSERT(sizeof(UINT_PTR) == sizeof(ULONG_PTR));
|
|
|
|
/* Undefine these to avoid conflicts with limits.h */
|
|
#undef CHAR_MIN
|
|
#undef CHAR_MAX
|
|
#undef INT_MIN
|
|
#undef INT_MAX
|
|
#undef LONG_MIN
|
|
#undef LONG_MAX
|
|
#undef UCHAR_MAX
|
|
#undef UINT_MAX
|
|
#undef ULONG_MAX
|
|
|
|
/* Integer range margins (use (x-1) to prevent warnings) */
|
|
#define INT8_MIN (-127 - 1)
|
|
#define SHORT_MIN (-32767 - 1)
|
|
#define INT16_MIN (-32767 - 1)
|
|
#define INT_MIN (-2147483647 - 1)
|
|
#define INT32_MIN (-2147483647 - 1)
|
|
#define LONG_MIN (-2147483647L - 1)
|
|
#define LONGLONG_MIN (-9223372036854775807LL - 1)
|
|
#define LONG64_MIN (-9223372036854775807LL - 1)
|
|
#define INT64_MIN (-9223372036854775807LL - 1)
|
|
//#define INT128_MIN (-170141183460469231731687303715884105728)
|
|
#ifdef _WIN64
|
|
#define INT_PTR_MIN INT64_MIN
|
|
#define LONG_PTR_MIN LONG64_MIN
|
|
#define PTRDIFF_T_MIN INT64_MIN
|
|
#define SSIZE_T_MIN INT64_MIN
|
|
#else // _WIN64
|
|
#define INT_PTR_MIN INT_MIN
|
|
#define LONG_PTR_MIN LONG_MIN
|
|
#define PTRDIFF_T_MIN INT_MIN
|
|
#define SSIZE_T_MIN INT_MIN
|
|
#endif // _WIN64
|
|
|
|
#define INT8_MAX 127
|
|
#define UINT8_MAX 0xff
|
|
#define UCHAR_MAX 0xff
|
|
#define BYTE_MAX 0xff
|
|
#define SHORT_MAX 32767
|
|
#define INT16_MAX 32767
|
|
#define USHORT_MAX 0xffff
|
|
#define UINT16_MAX 0xffff
|
|
#define WORD_MAX 0xffff
|
|
#define INT_MAX 2147483647
|
|
#define INT32_MAX 2147483647
|
|
#define UINT_MAX 0xffffffffU
|
|
#define UINT32_MAX 0xffffffffU
|
|
#define LONG_MAX 2147483647L
|
|
#define ULONG_MAX 0xffffffffUL
|
|
#define DWORD_MAX 0xffffffffUL
|
|
#define LONGLONG_MAX 9223372036854775807LL
|
|
#define LONG64_MAX 9223372036854775807LL
|
|
#define INT64_MAX 9223372036854775807LL
|
|
#define ULONGLONG_MAX 0xffffffffffffffffULL
|
|
#define DWORDLONG_MAX 0xffffffffffffffffULL
|
|
#define ULONG64_MAX 0xffffffffffffffffULL
|
|
#define DWORD64_MAX 0xffffffffffffffffULL
|
|
#define UINT64_MAX 0xffffffffffffffffULL
|
|
#define INT128_MAX 170141183460469231731687303715884105727
|
|
#define UINT128_MAX 0xffffffffffffffffffffffffffffffff
|
|
#undef SIZE_T_MAX
|
|
#ifdef _WIN64
|
|
#define INT_PTR_MAX INT64_MAX
|
|
#define UINT_PTR_MAX UINT64_MAX
|
|
#define LONG_PTR_MAX LONG64_MAX
|
|
#define ULONG_PTR_MAX ULONG64_MAX
|
|
#define DWORD_PTR_MAX DWORD64_MAX
|
|
#define PTRDIFF_T_MAX INT64_MAX
|
|
#define SIZE_T_MAX UINT64_MAX
|
|
#define SSIZE_T_MAX INT64_MAX
|
|
#define _SIZE_T_MAX UINT64_MAX
|
|
#else // _WIN64
|
|
#define INT_PTR_MAX INT_MAX
|
|
#define UINT_PTR_MAX UINT_MAX
|
|
#define LONG_PTR_MAX LONG_MAX
|
|
#define ULONG_PTR_MAX ULONG_MAX
|
|
#define DWORD_PTR_MAX DWORD_MAX
|
|
#define PTRDIFF_T_MAX INT_MAX
|
|
#define SIZE_T_MAX UINT_MAX
|
|
#define SSIZE_T_MAX INT_MAX
|
|
#define _SIZE_T_MAX UINT_MAX
|
|
#endif // _WIN64
|
|
|
|
#ifndef CHAR_MIN
|
|
#ifdef _CHAR_UNSIGNED
|
|
#define CHAR_MIN 0
|
|
#define CHAR_MAX 0xff
|
|
#else
|
|
#define CHAR_MIN (-128)
|
|
#define CHAR_MAX 127
|
|
#endif
|
|
#endif
|
|
|
|
/* Error values */
|
|
#define INT8_ERROR (-1)
|
|
#define UINT8_ERROR 0xff
|
|
#define BYTE_ERROR 0xff
|
|
#define SHORT_ERROR (-1)
|
|
#define INT16_ERROR (-1)
|
|
#define USHORT_ERROR 0xffff
|
|
#define UINT16_ERROR 0xffff
|
|
#define WORD_ERROR 0xffff
|
|
#define INT_ERROR (-1)
|
|
#define INT32_ERROR (-1)
|
|
#define UINT_ERROR 0xffffffff
|
|
#define UINT32_ERROR 0xffffffff
|
|
#define LONG_ERROR (-1L)
|
|
#define ULONG_ERROR 0xffffffffUL
|
|
#define DWORD_ERROR 0xffffffffUL
|
|
#define LONGLONG_ERROR (-1LL)
|
|
#define LONG64_ERROR (-1LL)
|
|
#define INT64_ERROR (-1LL)
|
|
#define ULONGLONG_ERROR 0xffffffffffffffffULL
|
|
#define DWORDLONG_ERROR 0xffffffffffffffffULL
|
|
#define ULONG64_ERROR 0xffffffffffffffffULL
|
|
#define UINT64_ERROR 0xffffffffffffffffULL
|
|
#ifdef _WIN64
|
|
#define INT_PTR_ERROR (-1LL)
|
|
#define UINT_PTR_ERROR 0xffffffffffffffffULL
|
|
#define LONG_PTR_ERROR (-1LL)
|
|
#define ULONG_PTR_ERROR 0xffffffffffffffffULL
|
|
#define DWORD_PTR_ERROR 0xffffffffffffffffULL
|
|
#define PTRDIFF_T_ERROR (-1LL)
|
|
#define SIZE_T_ERROR 0xffffffffffffffffULL
|
|
#define SSIZE_T_ERROR (-1LL)
|
|
#define _SIZE_T_ERROR 0xffffffffffffffffULL
|
|
#else // _WIN64
|
|
#define INT_PTR_ERROR (-1)
|
|
#define UINT_PTR_ERROR 0xffffffff
|
|
#define LONG_PTR_ERROR (-1L)
|
|
#define ULONG_PTR_ERROR 0xffffffffUL
|
|
#define DWORD_PTR_ERROR 0xffffffffUL
|
|
#define PTRDIFF_T_ERROR (-1)
|
|
#define SIZE_T_ERROR 0xffffffff
|
|
#define SSIZE_T_ERROR (-1L)
|
|
#define _SIZE_T_ERROR 0xffffffffUL
|
|
#endif // _WIN64
|
|
|
|
#define size_t_ERROR SIZE_T_ERROR
|
|
#define UCHAR_ERROR '\0'
|
|
#define CHAR_ERROR '\0'
|
|
|
|
|
|
/* 32 bit x 32 bit to 64 bit unsigned multiplication */
|
|
#ifndef UInt32x32To64
|
|
#define UInt32x32To64(a,b) ((DWORDLONG)(a)*(DWORDLONG)(b))
|
|
#endif
|
|
|
|
|
|
/* Convert unsigned to signed or unsigned */
|
|
#define DEFINE_SAFE_CONVERT_UTOX(_Name, _TypeFrom, _TypeTo) \
|
|
_Must_inspect_result_ \
|
|
__forceinline \
|
|
INTSAFE_RESULT \
|
|
INTSAFE_NAME(_Name)( \
|
|
_In_ _TypeFrom Input, \
|
|
_Out_ _Deref_out_range_(==, Input) _TypeTo *pOutput) \
|
|
{ \
|
|
if (Input <= _TypeTo ## _MAX) \
|
|
{ \
|
|
*pOutput = (_TypeTo)Input; \
|
|
return INTSAFE_SUCCESS; \
|
|
} \
|
|
else \
|
|
{ \
|
|
*pOutput = _TypeTo ## _ERROR; \
|
|
return INTSAFE_E_ARITHMETIC_OVERFLOW; \
|
|
} \
|
|
}
|
|
|
|
DEFINE_SAFE_CONVERT_UTOX(ByteToChar, BYTE, CHAR)
|
|
DEFINE_SAFE_CONVERT_UTOX(ByteToInt8, BYTE, INT8)
|
|
DEFINE_SAFE_CONVERT_UTOX(UInt8ToChar, UINT8, CHAR)
|
|
DEFINE_SAFE_CONVERT_UTOX(UInt8ToInt8, UINT8, INT8)
|
|
DEFINE_SAFE_CONVERT_UTOX(UShortToChar, USHORT, CHAR)
|
|
DEFINE_SAFE_CONVERT_UTOX(UShortToUChar, USHORT, UCHAR)
|
|
DEFINE_SAFE_CONVERT_UTOX(UShortToInt8, USHORT, INT8)
|
|
DEFINE_SAFE_CONVERT_UTOX(UShortToUInt8, USHORT, UINT8)
|
|
DEFINE_SAFE_CONVERT_UTOX(UShortToShort, USHORT, SHORT)
|
|
DEFINE_SAFE_CONVERT_UTOX(UIntToUChar, UINT, UCHAR)
|
|
DEFINE_SAFE_CONVERT_UTOX(UIntToInt8, UINT, INT8)
|
|
DEFINE_SAFE_CONVERT_UTOX(UIntToUInt8, UINT, UINT8)
|
|
DEFINE_SAFE_CONVERT_UTOX(UIntToShort, UINT, SHORT)
|
|
DEFINE_SAFE_CONVERT_UTOX(UIntToUShort, UINT, USHORT)
|
|
DEFINE_SAFE_CONVERT_UTOX(UIntToInt, UINT, INT)
|
|
DEFINE_SAFE_CONVERT_UTOX(UIntToLong, UINT, LONG)
|
|
DEFINE_SAFE_CONVERT_UTOX(UIntPtrToUChar, UINT_PTR, UCHAR)
|
|
DEFINE_SAFE_CONVERT_UTOX(UIntPtrToInt8, UINT_PTR, INT8)
|
|
DEFINE_SAFE_CONVERT_UTOX(UIntPtrToUInt8, UINT_PTR, UINT8)
|
|
DEFINE_SAFE_CONVERT_UTOX(UIntPtrToShort, UINT_PTR, SHORT)
|
|
DEFINE_SAFE_CONVERT_UTOX(UIntPtrToUShort, UINT_PTR, USHORT)
|
|
DEFINE_SAFE_CONVERT_UTOX(UIntPtrToInt16, UINT_PTR, INT16)
|
|
DEFINE_SAFE_CONVERT_UTOX(UIntPtrToUInt16, UINT_PTR, UINT16)
|
|
DEFINE_SAFE_CONVERT_UTOX(UIntPtrToInt, UINT_PTR, INT)
|
|
DEFINE_SAFE_CONVERT_UTOX(UIntPtrToLong, UINT_PTR, LONG)
|
|
DEFINE_SAFE_CONVERT_UTOX(UIntPtrToIntPtr, UINT_PTR, INT_PTR)
|
|
DEFINE_SAFE_CONVERT_UTOX(UIntPtrToLongPtr, UINT_PTR, LONG_PTR)
|
|
DEFINE_SAFE_CONVERT_UTOX(ULongToUChar, ULONG, UCHAR)
|
|
DEFINE_SAFE_CONVERT_UTOX(ULongToUInt8, ULONG, UINT8)
|
|
DEFINE_SAFE_CONVERT_UTOX(ULongToShort, ULONG, SHORT)
|
|
DEFINE_SAFE_CONVERT_UTOX(ULongToUShort, ULONG, USHORT)
|
|
DEFINE_SAFE_CONVERT_UTOX(ULongToInt, ULONG, INT)
|
|
DEFINE_SAFE_CONVERT_UTOX(ULongToUInt, ULONG, UINT)
|
|
DEFINE_SAFE_CONVERT_UTOX(ULongToIntPtr, ULONG, INT_PTR)
|
|
DEFINE_SAFE_CONVERT_UTOX(ULongToUIntPtr, ULONG, UINT_PTR)
|
|
DEFINE_SAFE_CONVERT_UTOX(ULongToLongPtr, ULONG, LONG_PTR)
|
|
DEFINE_SAFE_CONVERT_UTOX(ULongPtrToULong, ULONG_PTR, ULONG)
|
|
DEFINE_SAFE_CONVERT_UTOX(ULongLongToUInt, ULONGLONG, UINT)
|
|
DEFINE_SAFE_CONVERT_UTOX(ULongLongToULong, ULONGLONG, ULONG)
|
|
DEFINE_SAFE_CONVERT_UTOX(ULongLongToULongPtr, ULONGLONG, ULONG_PTR)
|
|
|
|
|
|
/* Convert signed to unsigned */
|
|
#define DEFINE_SAFE_CONVERT_STOU(_Name, _TypeFrom, _TypeTo) \
|
|
_Must_inspect_result_ \
|
|
__forceinline \
|
|
INTSAFE_RESULT \
|
|
INTSAFE_NAME(_Name)( \
|
|
_In_ _TypeFrom Input, \
|
|
_Out_ _Deref_out_range_(==, Input) _TypeTo *pOutput) \
|
|
{ \
|
|
if ((Input >= 0) && \
|
|
((sizeof(_TypeFrom) <= sizeof(_TypeTo)) || (Input <= (_TypeFrom)_TypeTo ## _MAX))) \
|
|
{ \
|
|
*pOutput = (_TypeTo)Input; \
|
|
return INTSAFE_SUCCESS; \
|
|
} \
|
|
else \
|
|
{ \
|
|
*pOutput = _TypeTo ## _ERROR; \
|
|
return INTSAFE_E_ARITHMETIC_OVERFLOW; \
|
|
} \
|
|
}
|
|
|
|
DEFINE_SAFE_CONVERT_STOU(Int8ToUChar, INT8, UCHAR)
|
|
DEFINE_SAFE_CONVERT_STOU(Int8ToUInt8, INT8, UINT8)
|
|
DEFINE_SAFE_CONVERT_STOU(Int8ToUShort, INT8, USHORT)
|
|
DEFINE_SAFE_CONVERT_STOU(Int8ToUInt, INT8, UINT)
|
|
DEFINE_SAFE_CONVERT_STOU(Int8ToULong, INT8, ULONG)
|
|
DEFINE_SAFE_CONVERT_STOU(Int8ToUIntPtr, INT8, UINT_PTR)
|
|
DEFINE_SAFE_CONVERT_STOU(Int8ToULongPtr, INT8, ULONG_PTR)
|
|
DEFINE_SAFE_CONVERT_STOU(Int8ToULongLong, INT8, ULONGLONG)
|
|
DEFINE_SAFE_CONVERT_STOU(ShortToUChar, SHORT, UCHAR)
|
|
DEFINE_SAFE_CONVERT_STOU(ShortToUInt8, SHORT, UINT8)
|
|
DEFINE_SAFE_CONVERT_STOU(ShortToUShort, SHORT, USHORT)
|
|
DEFINE_SAFE_CONVERT_STOU(ShortToUInt, SHORT, UINT)
|
|
DEFINE_SAFE_CONVERT_STOU(ShortToULong, SHORT, ULONG)
|
|
DEFINE_SAFE_CONVERT_STOU(ShortToUIntPtr, SHORT, UINT_PTR)
|
|
DEFINE_SAFE_CONVERT_STOU(ShortToULongPtr, SHORT, ULONG_PTR)
|
|
DEFINE_SAFE_CONVERT_STOU(ShortToDWordPtr, SHORT, DWORD_PTR)
|
|
DEFINE_SAFE_CONVERT_STOU(ShortToULongLong, SHORT, ULONGLONG)
|
|
DEFINE_SAFE_CONVERT_STOU(IntToUChar, INT, UCHAR)
|
|
DEFINE_SAFE_CONVERT_STOU(IntToUInt8, INT, UINT8)
|
|
DEFINE_SAFE_CONVERT_STOU(IntToUShort, INT, USHORT)
|
|
DEFINE_SAFE_CONVERT_STOU(IntToUInt, INT, UINT)
|
|
DEFINE_SAFE_CONVERT_STOU(IntToULong, INT, ULONG)
|
|
DEFINE_SAFE_CONVERT_STOU(IntToULongLong, INT, ULONGLONG)
|
|
DEFINE_SAFE_CONVERT_STOU(LongToUChar, LONG, UCHAR)
|
|
DEFINE_SAFE_CONVERT_STOU(LongToUInt8, LONG, UINT8)
|
|
DEFINE_SAFE_CONVERT_STOU(LongToUShort, LONG, USHORT)
|
|
DEFINE_SAFE_CONVERT_STOU(LongToUInt, LONG, UINT)
|
|
DEFINE_SAFE_CONVERT_STOU(LongToULong, LONG, ULONG)
|
|
DEFINE_SAFE_CONVERT_STOU(LongToUIntPtr, LONG, UINT_PTR)
|
|
DEFINE_SAFE_CONVERT_STOU(LongToULongPtr, LONG, ULONG_PTR)
|
|
DEFINE_SAFE_CONVERT_STOU(LongToULongLong, LONG, ULONGLONG)
|
|
DEFINE_SAFE_CONVERT_STOU(IntPtrToUChar, INT_PTR, UCHAR)
|
|
DEFINE_SAFE_CONVERT_STOU(IntPtrToUInt8, INT_PTR, UINT8)
|
|
DEFINE_SAFE_CONVERT_STOU(IntPtrToUShort, INT_PTR, USHORT)
|
|
DEFINE_SAFE_CONVERT_STOU(IntPtrToUInt, INT_PTR, UINT)
|
|
DEFINE_SAFE_CONVERT_STOU(IntPtrToULong, INT_PTR, ULONG)
|
|
DEFINE_SAFE_CONVERT_STOU(IntPtrToUIntPtr, INT_PTR, UINT_PTR)
|
|
DEFINE_SAFE_CONVERT_STOU(IntPtrToULongPtr, INT_PTR, ULONG_PTR)
|
|
DEFINE_SAFE_CONVERT_STOU(IntPtrToULongLong, INT_PTR, ULONGLONG)
|
|
DEFINE_SAFE_CONVERT_STOU(LongPtrToUChar, LONG_PTR, UCHAR)
|
|
DEFINE_SAFE_CONVERT_STOU(LongPtrToUInt8, LONG_PTR, UINT8)
|
|
DEFINE_SAFE_CONVERT_STOU(LongPtrToUShort, LONG_PTR, USHORT)
|
|
DEFINE_SAFE_CONVERT_STOU(LongPtrToUInt, LONG_PTR, UINT)
|
|
DEFINE_SAFE_CONVERT_STOU(LongPtrToULong, LONG_PTR, ULONG)
|
|
DEFINE_SAFE_CONVERT_STOU(LongPtrToUIntPtr, LONG_PTR, UINT_PTR)
|
|
DEFINE_SAFE_CONVERT_STOU(LongPtrToULongPtr, LONG_PTR, ULONG_PTR)
|
|
DEFINE_SAFE_CONVERT_STOU(LongPtrToULongLong, LONG_PTR, ULONGLONG)
|
|
#ifdef _CHAR_UNSIGNED
|
|
DEFINE_SAFE_CONVERT_STOU(ShortToChar, SHORT, UCHAR)
|
|
DEFINE_SAFE_CONVERT_STOU(LongPtrToChar, LONG_PTR, UCHAR)
|
|
#endif
|
|
|
|
|
|
/* Convert signed to signed */
|
|
#define DEFINE_SAFE_CONVERT_STOS(_Name, _TypeFrom, _TypeTo) \
|
|
_Must_inspect_result_ \
|
|
__forceinline \
|
|
INTSAFE_RESULT \
|
|
INTSAFE_NAME(_Name)( \
|
|
_In_ _TypeFrom Input, \
|
|
_Out_ _Deref_out_range_(==, Input) _TypeTo *pOutput) \
|
|
{ \
|
|
if ((Input >= _TypeTo ## _MIN) && (Input <= _TypeTo ## _MAX)) \
|
|
{ \
|
|
*pOutput = (_TypeTo)Input; \
|
|
return INTSAFE_SUCCESS; \
|
|
} \
|
|
else \
|
|
{ \
|
|
*pOutput = _TypeTo ## _ERROR; \
|
|
return INTSAFE_E_ARITHMETIC_OVERFLOW; \
|
|
} \
|
|
}
|
|
|
|
DEFINE_SAFE_CONVERT_STOS(ShortToInt8, SHORT, INT8)
|
|
DEFINE_SAFE_CONVERT_STOS(IntToInt8, INT, INT8)
|
|
DEFINE_SAFE_CONVERT_STOS(IntToShort, INT, SHORT)
|
|
DEFINE_SAFE_CONVERT_STOS(LongToInt8, LONG, INT8)
|
|
DEFINE_SAFE_CONVERT_STOS(LongToShort, LONG, SHORT)
|
|
DEFINE_SAFE_CONVERT_STOS(LongToInt, LONG, INT)
|
|
DEFINE_SAFE_CONVERT_STOS(IntPtrToInt8, INT_PTR, INT8)
|
|
DEFINE_SAFE_CONVERT_STOS(IntPtrToShort, INT_PTR, SHORT)
|
|
DEFINE_SAFE_CONVERT_STOS(IntPtrToInt, INT_PTR, INT)
|
|
DEFINE_SAFE_CONVERT_STOS(IntPtrToLong, INT_PTR, LONG)
|
|
DEFINE_SAFE_CONVERT_STOS(IntPtrToLongPtr, INT_PTR, LONG_PTR)
|
|
DEFINE_SAFE_CONVERT_STOS(LongPtrToInt8, LONG_PTR, INT8)
|
|
DEFINE_SAFE_CONVERT_STOS(LongPtrToShort, LONG_PTR, SHORT)
|
|
DEFINE_SAFE_CONVERT_STOS(LongPtrToInt, LONG_PTR, INT)
|
|
DEFINE_SAFE_CONVERT_STOS(LongPtrToLong, LONG_PTR, LONG)
|
|
DEFINE_SAFE_CONVERT_STOS(LongPtrToIntPtr, LONG_PTR, INT_PTR)
|
|
DEFINE_SAFE_CONVERT_STOS(LongLongToLong, LONGLONG, LONG)
|
|
DEFINE_SAFE_CONVERT_STOS(LongLongToIntPtr, LONGLONG, INT_PTR)
|
|
DEFINE_SAFE_CONVERT_STOS(LongLongToLongPtr, LONGLONG, LONG_PTR)
|
|
#ifndef _CHAR_UNSIGNED
|
|
DEFINE_SAFE_CONVERT_STOS(ShortToChar, SHORT, CHAR)
|
|
DEFINE_SAFE_CONVERT_STOS(LongPtrToChar, LONG_PTR, CHAR)
|
|
#endif
|
|
|
|
|
|
#ifdef _NTINTSAFE_H_INCLUDED_
|
|
|
|
#define RtlInt8ToByte RtlInt8ToUInt8
|
|
#define RtlInt8ToUInt16 RtlInt8ToUShort
|
|
#define RtlInt8ToWord RtlInt8ToUShort
|
|
#define RtlInt8ToUInt32 RtlInt8ToUInt
|
|
#define RtlInt8ToDWord RtlInt8ToULong
|
|
#define RtlInt8ToDWordPtr RtlInt8ToULongPtr
|
|
#define RtlInt8ToDWordLong RtlInt8ToULongLong
|
|
#define RtlInt8ToULong64 RtlInt8ToULongLong
|
|
#define RtlInt8ToDWord64 RtlInt8ToULongLong
|
|
#define RtlInt8ToUInt64 RtlInt8ToULongLong
|
|
#define RtlInt8ToSizeT RtlInt8ToUIntPtr
|
|
#define RtlInt8ToSIZET RtlInt8ToULongPtr
|
|
#define RtlIntToSizeT RtlIntToUIntPtr
|
|
#define RtlIntToSIZET RtlIntToULongPtr
|
|
#define RtlULongToSSIZET RtlULongToLongPtr
|
|
#define RtlULongToByte RtlULongToUInt8
|
|
#define RtlULongLongToInt64 RtlULongLongToLongLong
|
|
#define RtlULongLongToLong64 RtlULongLongToLongLong
|
|
#define RtlULongLongToPtrdiffT RtlULongLongToIntPtr
|
|
#define RtlULongLongToSizeT RtlULongLongToUIntPtr
|
|
#define RtlULongLongToSSIZET RtlULongLongToLongPtr
|
|
#define RtlULongLongToSIZET RtlULongLongToULongPtr
|
|
#define RtlSIZETToULong RtlULongPtrToULong
|
|
#define RtlSSIZETToULongLong RtlLongPtrToULongLong
|
|
#define RtlSSIZETToULong RtlLongPtrToULong
|
|
#ifdef _WIN64
|
|
#define RtlIntToUIntPtr RtlIntToULongLong
|
|
#define RtlULongLongToIntPtr RtlULongLongToLongLong
|
|
#else
|
|
#define RtlIntToUIntPtr RtlIntToUInt
|
|
#define RtlULongLongToIntPtr RtlULongLongToInt
|
|
#define RtlULongLongToUIntPtr RtlULongLongToUInt
|
|
#define RtlULongLongToULongPtr RtlULongLongToULong
|
|
#endif
|
|
|
|
#else // _NTINTSAFE_H_INCLUDED_
|
|
|
|
#define Int8ToByte Int8ToUInt8
|
|
#define Int8ToUInt16 Int8ToUShort
|
|
#define Int8ToWord Int8ToUShort
|
|
#define Int8ToUInt32 Int8ToUInt
|
|
#define Int8ToDWord Int8ToULong
|
|
#define Int8ToDWordPtr Int8ToULongPtr
|
|
#define Int8ToDWordLong Int8ToULongLong
|
|
#define Int8ToULong64 Int8ToULongLong
|
|
#define Int8ToDWord64 Int8ToULongLong
|
|
#define Int8ToUInt64 Int8ToULongLong
|
|
#define Int8ToSizeT Int8ToUIntPtr
|
|
#define Int8ToSIZET Int8ToULongPtr
|
|
#define IntToSizeT IntToUIntPtr
|
|
#define IntToSIZET IntToULongPtr
|
|
#define ULongToSSIZET ULongToLongPtr
|
|
#define ULongToByte ULongToUInt8
|
|
#define ULongLongToInt64 ULongLongToLongLong
|
|
#define ULongLongToLong64 ULongLongToLongLong
|
|
#define ULongLongToPtrdiffT ULongLongToIntPtr
|
|
#define ULongLongToSizeT ULongLongToUIntPtr
|
|
#define ULongLongToSSIZET ULongLongToLongPtr
|
|
#define ULongLongToSIZET ULongLongToULongPtr
|
|
#define SIZETToULong ULongPtrToULong
|
|
#define SSIZETToULongLong LongPtrToULongLong
|
|
#define SSIZETToULong LongPtrToULong
|
|
#ifdef _WIN64
|
|
#define IntToUIntPtr IntToULongLong
|
|
#define ULongLongToIntPtr ULongLongToLongLong
|
|
#else
|
|
#define IntToUIntPtr IntToUInt
|
|
#define ULongLongToIntPtr ULongLongToInt
|
|
#define ULongLongToUIntPtr ULongLongToUInt
|
|
#define ULongLongToULongPtr ULongLongToULong
|
|
#endif
|
|
|
|
#endif // _NTINTSAFE_H_INCLUDED_
|
|
|
|
|
|
#define DEFINE_SAFE_ADD(_Name, _Type) \
|
|
_Must_inspect_result_ \
|
|
__forceinline \
|
|
INTSAFE_RESULT \
|
|
INTSAFE_NAME(_Name)( \
|
|
_In_ _Type Augend, \
|
|
_In_ _Type Addend, \
|
|
_Out_ _Deref_out_range_(==, Augend + Addend) _Type *pOutput) \
|
|
{ \
|
|
if ((Augend + Addend) >= Augend) \
|
|
{ \
|
|
*pOutput = Augend + Addend; \
|
|
return INTSAFE_SUCCESS; \
|
|
} \
|
|
else \
|
|
{ \
|
|
*pOutput = _Type ## _ERROR; \
|
|
return INTSAFE_E_ARITHMETIC_OVERFLOW; \
|
|
} \
|
|
}
|
|
|
|
DEFINE_SAFE_ADD(UInt8Add, UINT8)
|
|
DEFINE_SAFE_ADD(UShortAdd, USHORT)
|
|
DEFINE_SAFE_ADD(UIntAdd, UINT)
|
|
DEFINE_SAFE_ADD(ULongAdd, ULONG)
|
|
DEFINE_SAFE_ADD(UIntPtrAdd, UINT_PTR)
|
|
DEFINE_SAFE_ADD(ULongPtrAdd, ULONG_PTR)
|
|
DEFINE_SAFE_ADD(DWordPtrAdd, DWORD_PTR)
|
|
DEFINE_SAFE_ADD(SizeTAdd, size_t)
|
|
DEFINE_SAFE_ADD(SIZETAdd, SIZE_T)
|
|
DEFINE_SAFE_ADD(ULongLongAdd, ULONGLONG)
|
|
|
|
|
|
#define DEFINE_SAFE_SUB(_Name, _Type) \
|
|
_Must_inspect_result_ \
|
|
__forceinline \
|
|
INTSAFE_RESULT \
|
|
INTSAFE_NAME(_Name)( \
|
|
_In_ _Type Minuend, \
|
|
_In_ _Type Subtrahend, \
|
|
_Out_ _Deref_out_range_(==, Minuend - Subtrahend) _Type* pOutput) \
|
|
{ \
|
|
if (Minuend >= Subtrahend) \
|
|
{ \
|
|
*pOutput = Minuend - Subtrahend; \
|
|
return INTSAFE_SUCCESS; \
|
|
} \
|
|
else \
|
|
{ \
|
|
*pOutput = _Type ## _ERROR; \
|
|
return INTSAFE_E_ARITHMETIC_OVERFLOW; \
|
|
} \
|
|
}
|
|
|
|
DEFINE_SAFE_SUB(UInt8Sub, UINT8)
|
|
DEFINE_SAFE_SUB(UShortSub, USHORT)
|
|
DEFINE_SAFE_SUB(UIntSub, UINT)
|
|
DEFINE_SAFE_SUB(UIntPtrSub, UINT_PTR)
|
|
DEFINE_SAFE_SUB(ULongSub, ULONG)
|
|
DEFINE_SAFE_SUB(ULongPtrSub, ULONG_PTR)
|
|
DEFINE_SAFE_SUB(DWordPtrSub, DWORD_PTR)
|
|
DEFINE_SAFE_SUB(SizeTSub, size_t)
|
|
DEFINE_SAFE_SUB(SIZETSub, SIZE_T)
|
|
DEFINE_SAFE_SUB(ULongLongSub, ULONGLONG)
|
|
|
|
|
|
_Must_inspect_result_
|
|
__forceinline
|
|
INTSAFE_RESULT
|
|
INTSAFE_NAME(LongLongSub)(
|
|
_In_ LONGLONG Minuend,
|
|
_In_ LONGLONG Subtrahend,
|
|
_Out_ _Deref_out_range_(==, Minuend - Subtrahend) LONGLONG* pResult)
|
|
{
|
|
LONGLONG Result = Minuend - Subtrahend;
|
|
|
|
/* The only way the result can overflow, is when the sign of the minuend
|
|
and the subtrahend differ. In that case the result is expected to
|
|
have the same sign as the minuend, otherwise it overflowed.
|
|
Sign equality is checked with a binary xor operation. */
|
|
if ( ((Minuend ^ Subtrahend) < 0) && ((Minuend ^ Result) < 0) )
|
|
{
|
|
*pResult = LONGLONG_ERROR;
|
|
return INTSAFE_E_ARITHMETIC_OVERFLOW;
|
|
}
|
|
else
|
|
{
|
|
*pResult = Result;
|
|
return INTSAFE_SUCCESS;
|
|
}
|
|
}
|
|
|
|
|
|
#define DEFINE_SAFE_SUB_S(_Name, _Type1, _Type2, _Convert) \
|
|
_Must_inspect_result_ \
|
|
__forceinline \
|
|
INTSAFE_RESULT \
|
|
INTSAFE_NAME(_Name)( \
|
|
_In_ _Type1 Minuend, \
|
|
_In_ _Type1 Subtrahend, \
|
|
_Out_ _Deref_out_range_(==, Minuend - Subtrahend) _Type1* pOutput) \
|
|
{ \
|
|
return INTSAFE_NAME(_Convert)(((_Type2)Minuend) - ((_Type2)Subtrahend), pOutput); \
|
|
}
|
|
|
|
DEFINE_SAFE_SUB_S(LongSub, LONG, LONGLONG, LongLongToLong)
|
|
#ifndef _WIN64
|
|
DEFINE_SAFE_SUB_S(IntPtrSub, INT_PTR, LONGLONG, LongLongToIntPtr)
|
|
DEFINE_SAFE_SUB_S(LongPtrSub, LONG_PTR, LONGLONG, LongLongToLongPtr)
|
|
#endif
|
|
|
|
|
|
_Must_inspect_result_
|
|
__forceinline
|
|
INTSAFE_RESULT
|
|
INTSAFE_NAME(ULongLongMult)(
|
|
_In_ ULONGLONG Multiplicand,
|
|
_In_ ULONGLONG Multiplier,
|
|
_Out_ _Deref_out_range_(==, Multiplicand * Multiplier) ULONGLONG* pOutput)
|
|
{
|
|
/* We can split the 64 bit numbers in low and high parts:
|
|
M1 = M1Low + M1Hi * 0x100000000
|
|
M2 = M2Low + M2Hi * 0x100000000
|
|
|
|
Then the multiplication looks like this:
|
|
M1 * M2 = (M1Low + M1Hi * 0x100000000) + (M2Low + M2Hi * 0x100000000)
|
|
= M1Low * M2Low
|
|
+ M1Low * M2Hi * 0x100000000
|
|
+ M2Low * M1Hi * 0x100000000
|
|
+ M1Hi * M2Hi * 0x100000000 * 0x100000000
|
|
|
|
We get an overflow when
|
|
a) M1Hi * M2Hi != 0, so when M1Hi and M2Hi are both not 0
|
|
b) The product of the nonzero high part and the other low part
|
|
is larger than 32 bits.
|
|
c) The addition of the product from b) shifted left by 32 and
|
|
M1Low * M2Low is larger than 64 bits
|
|
*/
|
|
ULONG M1Low = Multiplicand & 0xffffffff;
|
|
ULONG M2Low = Multiplier & 0xffffffff;
|
|
ULONG M1Hi = Multiplicand >> 32;
|
|
ULONG M2Hi = Multiplier >> 32;
|
|
ULONGLONG Temp;
|
|
|
|
if (M1Hi == 0)
|
|
{
|
|
Temp = UInt32x32To64(M1Low, M2Hi);
|
|
}
|
|
else if (M2Hi == 0)
|
|
{
|
|
Temp = UInt32x32To64(M1Hi, M2Low);
|
|
}
|
|
else
|
|
{
|
|
*pOutput = LONGLONG_ERROR;
|
|
return INTSAFE_E_ARITHMETIC_OVERFLOW;
|
|
}
|
|
|
|
if (Temp > ULONG_MAX)
|
|
{
|
|
*pOutput = LONGLONG_ERROR;
|
|
return INTSAFE_E_ARITHMETIC_OVERFLOW;
|
|
}
|
|
|
|
return INTSAFE_NAME(ULongLongAdd)(Temp << 32, UInt32x32To64(M1Low, M2Low), pOutput);
|
|
}
|
|
|
|
|
|
#define DEFINE_SAFE_MULT_U32(_Name, _Type, _Convert) \
|
|
_Must_inspect_result_ \
|
|
__forceinline \
|
|
INTSAFE_RESULT \
|
|
INTSAFE_NAME(_Name)( \
|
|
_In_ _Type Multiplicand, \
|
|
_In_ _Type Multiplier, \
|
|
_Out_ _Deref_out_range_(==, Multiplicand * Multiplier) _Type* pOutput) \
|
|
{ \
|
|
ULONGLONG Result = UInt32x32To64(Multiplicand, Multiplier); \
|
|
return INTSAFE_NAME(_Convert)(Result, pOutput); \
|
|
}
|
|
|
|
DEFINE_SAFE_MULT_U32(ULongMult, ULONG, ULongLongToULong)
|
|
#ifndef _WIN64
|
|
DEFINE_SAFE_MULT_U32(SizeTMult, size_t, ULongLongToSizeT)
|
|
DEFINE_SAFE_MULT_U32(SIZETMult, SIZE_T, ULongLongToSIZET)
|
|
#endif
|
|
|
|
#define DEFINE_SAFE_MULT_U16(_Name, _Type, _Convert) \
|
|
_Must_inspect_result_ \
|
|
__forceinline \
|
|
INTSAFE_RESULT \
|
|
INTSAFE_NAME(_Name)( \
|
|
_In_ _Type Multiplicand, \
|
|
_In_ _Type Multiplier, \
|
|
_Out_ _Deref_out_range_(==, Multiplicand * Multiplier) _Type* pOutput) \
|
|
{ \
|
|
ULONG Result = ((ULONG)Multiplicand) * ((ULONG)Multiplier); \
|
|
return INTSAFE_NAME(_Convert)(Result, pOutput); \
|
|
}
|
|
|
|
DEFINE_SAFE_MULT_U16(UShortMult, USHORT, ULongToUShort)
|
|
|
|
|
|
#ifdef _NTINTSAFE_H_INCLUDED_
|
|
|
|
#define RtlUInt16Add RtlUShortAdd
|
|
#define RtlWordAdd RtlUShortAdd
|
|
#define RtlUInt32Add RtlUIntAdd
|
|
#define RtlDWordAdd RtlULongAdd
|
|
#define RtlDWordLongAdd RtlULongLongAdd
|
|
#define RtlULong64Add RtlULongLongAdd
|
|
#define RtlDWord64Add RtlULongLongAdd
|
|
#define RtlUInt64Add RtlULongLongAdd
|
|
#define RtlUInt16Sub RtlUShortSub
|
|
#define RtlWordSub RtlUShortSub
|
|
#define RtlUInt32Sub RtlUIntSub
|
|
#define RtlDWordSub RtlULongSub
|
|
#define RtlDWordLongSub RtlULongLongSub
|
|
#define RtlULong64Sub RtlULongLongSub
|
|
#define RtlDWord64Sub RtlULongLongSub
|
|
#define RtlUInt64Sub RtlULongLongSub
|
|
#define RtlUInt16Mult RtlUShortMult
|
|
#define RtlWordMult RtlUShortMult
|
|
#ifdef _WIN64
|
|
#define RtlIntPtrSub RtlLongLongSub
|
|
#define RtlLongPtrSub RtlLongLongSub
|
|
#define RtlSizeTMult RtlULongLongMult
|
|
#define RtlSIZETMult RtlULongLongMult
|
|
#else
|
|
#endif
|
|
|
|
#else // _NTINTSAFE_H_INCLUDED_
|
|
|
|
#define UInt16Add UShortAdd
|
|
#define WordAdd UShortAdd
|
|
#define UInt32Add UIntAdd
|
|
#define DWordAdd ULongAdd
|
|
#define DWordLongAdd ULongLongAdd
|
|
#define ULong64Add ULongLongAdd
|
|
#define DWord64Add ULongLongAdd
|
|
#define UInt64Add ULongLongAdd
|
|
#define UInt16Sub UShortSub
|
|
#define WordSub UShortSub
|
|
#define UInt32Sub UIntSub
|
|
#define DWordSub ULongSub
|
|
#define DWordLongSub ULongLongSub
|
|
#define ULong64Sub ULongLongSub
|
|
#define DWord64Sub ULongLongSub
|
|
#define UInt64Sub ULongLongSub
|
|
#define UInt16Mult UShortMult
|
|
#define WordMult UShortMult
|
|
#ifdef _WIN64
|
|
#define IntPtrSub LongLongSub
|
|
#define LongPtrSub LongLongSub
|
|
#define SizeTMult ULongLongMult
|
|
#define SIZETMult ULongLongMult
|
|
#else
|
|
#endif
|
|
|
|
#endif // _NTINTSAFE_H_INCLUDED_
|
|
|
|
#endif // !_INTSAFE_H_INCLUDED_
|