diff --git a/cxplat/cxplat_test/cxplat_size_test.cpp b/cxplat/cxplat_test/cxplat_size_test.cpp new file mode 100644 index 0000000..a71b41d --- /dev/null +++ b/cxplat/cxplat_test/cxplat_size_test.cpp @@ -0,0 +1,36 @@ +// Copyright (c) Microsoft Corporation +// SPDX-License-Identifier: MIT + +#if !defined(CMAKE_NUGET) +#include +#else +#include +#endif +#include "cxplat.h" + +TEST_CASE("cxplat_safe_size_t_multiply", "[size]") +{ + size_t result; + REQUIRE(cxplat_safe_size_t_multiply(3, 5, &result) == CXPLAT_STATUS_SUCCESS); + REQUIRE(result == 15); + + REQUIRE(cxplat_safe_size_t_multiply(SIZE_MAX, 2, &result) == CXPLAT_STATUS_ARITHMETIC_OVERFLOW); +} + +TEST_CASE("cxplat_safe_size_t_add", "[size]") +{ + size_t result; + REQUIRE(cxplat_safe_size_t_add(3, 5, &result) == CXPLAT_STATUS_SUCCESS); + REQUIRE(result == 8); + + REQUIRE(cxplat_safe_size_t_add(SIZE_MAX, 2, &result) == CXPLAT_STATUS_ARITHMETIC_OVERFLOW); +} + +TEST_CASE("cxplat_safe_size_t_subtract", "[size]") +{ + size_t result; + REQUIRE(cxplat_safe_size_t_subtract(5, 3, &result) == CXPLAT_STATUS_SUCCESS); + REQUIRE(result == 2); + + REQUIRE(cxplat_safe_size_t_subtract(3, 5, &result) == CXPLAT_STATUS_ARITHMETIC_OVERFLOW); +} \ No newline at end of file diff --git a/cxplat/cxplat_test/cxplat_test.vcxproj b/cxplat/cxplat_test/cxplat_test.vcxproj index b7e6216..20025f1 100644 --- a/cxplat/cxplat_test/cxplat_test.vcxproj +++ b/cxplat/cxplat_test/cxplat_test.vcxproj @@ -131,6 +131,7 @@ + diff --git a/cxplat/cxplat_test/cxplat_test.vcxproj.filters b/cxplat/cxplat_test/cxplat_test.vcxproj.filters index ea10dd5..afa92f7 100644 --- a/cxplat/cxplat_test/cxplat_test.vcxproj.filters +++ b/cxplat/cxplat_test/cxplat_test.vcxproj.filters @@ -18,6 +18,9 @@ Source Files + + Source Files + diff --git a/cxplat/inc/cxplat.h b/cxplat/inc/cxplat.h index b254fad..9b9b904 100644 --- a/cxplat/inc/cxplat.h +++ b/cxplat/inc/cxplat.h @@ -4,6 +4,7 @@ #include "cxplat_fault_injection.h" #include "cxplat_memory.h" +#include "cxplat_size.h" CXPLAT_EXTERN_C_BEGIN diff --git a/cxplat/inc/cxplat_common.h b/cxplat/inc/cxplat_common.h index 5dd2f6a..b20170d 100644 --- a/cxplat/inc/cxplat_common.h +++ b/cxplat/inc/cxplat_common.h @@ -34,4 +34,5 @@ typedef _Return_type_success_(CXPLAT_SUCCEEDED(return )) enum { CXPLAT_STATUS_SUCCESS = CXPLAT_PLATFORM_STATUS_SUCCESS, CXPLAT_STATUS_NO_MEMORY = CXPLAT_PLATFORM_STATUS_NO_MEMORY, + CXPLAT_STATUS_ARITHMETIC_OVERFLOW = CXPLAT_PLATFORM_STATUS_ARITHMETIC_OVERFLOW, } cxplat_status_t; diff --git a/cxplat/inc/cxplat_size.h b/cxplat/inc/cxplat_size.h new file mode 100644 index 0000000..dc3a10e --- /dev/null +++ b/cxplat/inc/cxplat_size.h @@ -0,0 +1,48 @@ +// Copyright (c) Microsoft Corporation +// SPDX-License-Identifier: MIT +#pragma once + +#include "cxplat_common.h" +#include + +CXPLAT_EXTERN_C_BEGIN + +/** + * @brief Multiplies one value of type size_t by another and check for + * overflow. + * @param[in] multiplicand The value to be multiplied by multiplier. + * @param[in] multiplier The value by which to multiply multiplicand. + * @param[out] result A pointer to the result. + * @retval CXPLAT_STATUS_SUCCESS The operation was successful. + * @retval CXPLAT_STATUS_ARITHMETIC_OVERFLOW Multiplication overflowed. + */ +_Must_inspect_result_ cxplat_status_t +cxplat_safe_size_t_multiply( + size_t multiplicand, size_t multiplier, _Out_ _Deref_out_range_(==, multiplicand* multiplier) size_t* result); + +/** + * @brief Add one value of type size_t by another and check for + * overflow. + * @param[in] augend The value to be added by addend. + * @param[in] addend The value add to augend. + * @param[out] result A pointer to the result. + * @retval CXPLAT_STATUS_SUCCESS The operation was successful. + * @retval CXPLAT_STATUS_ARITHMETIC_OVERFLOW Addition overflowed. + */ +_Must_inspect_result_ cxplat_status_t +cxplat_safe_size_t_add(size_t augend, size_t addend, _Out_ _Deref_out_range_(==, augend + addend) size_t* result); + +/** + * @brief Subtract one value of type size_t from another and check for + * overflow or underflow. + * @param[in] minuend The value from which subtrahend is subtracted. + * @param[in] subtrahend The value subtract from minuend. + * @param[out] result A pointer to the result. + * @retval CXPLAT_STATUS_SUCCESS The operation was successful. + * @retval CXPLAT_STATUS_ARITHMETIC_OVERFLOW Addition overflowed or underflowed. + */ +_Must_inspect_result_ cxplat_status_t +cxplat_safe_size_t_subtract( + size_t minuend, size_t subtrahend, _Out_ _Deref_out_range_(==, minuend - subtrahend) size_t* result); + +CXPLAT_EXTERN_C_END diff --git a/cxplat/inc/winkernel/cxplat_winkernel.h b/cxplat/inc/winkernel/cxplat_winkernel.h index e4e744b..05477b3 100644 --- a/cxplat/inc/winkernel/cxplat_winkernel.h +++ b/cxplat/inc/winkernel/cxplat_winkernel.h @@ -10,5 +10,6 @@ // Map specific cxplat_status_t values to HRESULT values. #define CXPLAT_PLATFORM_STATUS_SUCCESS STATUS_SUCCESS #define CXPLAT_PLATFORM_STATUS_NO_MEMORY STATUS_NO_MEMORY +#define CXPLAT_PLATFORM_STATUS_ARITHMETIC_OVERFLOW STATUS_INTEGER_OVERFLOW #define CXPLAT_SUCCEEDED(status) NT_SUCCESS(status) diff --git a/cxplat/inc/winuser/cxplat_winuser.h b/cxplat/inc/winuser/cxplat_winuser.h index 516e517..c75f179 100644 --- a/cxplat/inc/winuser/cxplat_winuser.h +++ b/cxplat/inc/winuser/cxplat_winuser.h @@ -6,5 +6,6 @@ // Map specific cxplat_status_t values to HRESULT values. #define CXPLAT_PLATFORM_STATUS_SUCCESS S_OK #define CXPLAT_PLATFORM_STATUS_NO_MEMORY __HRESULT_FROM_WIN32(ERROR_OUTOFMEMORY) +#define CXPLAT_PLATFORM_STATUS_ARITHMETIC_OVERFLOW __HRESULT_FROM_WIN32(ERROR_ARITHMETIC_OVERFLOW) #define CXPLAT_SUCCEEDED(status) SUCCEEDED((HRESULT)(status)) diff --git a/cxplat/src/cxplat_winkernel/cxplat_winkernel.vcxproj b/cxplat/src/cxplat_winkernel/cxplat_winkernel.vcxproj index e09fb18..6a48161 100644 --- a/cxplat/src/cxplat_winkernel/cxplat_winkernel.vcxproj +++ b/cxplat/src/cxplat_winkernel/cxplat_winkernel.vcxproj @@ -33,12 +33,14 @@ + + diff --git a/cxplat/src/cxplat_winkernel/cxplat_winkernel.vcxproj.filters b/cxplat/src/cxplat_winkernel/cxplat_winkernel.vcxproj.filters index 458d5bc..594f0fe 100644 --- a/cxplat/src/cxplat_winkernel/cxplat_winkernel.vcxproj.filters +++ b/cxplat/src/cxplat_winkernel/cxplat_winkernel.vcxproj.filters @@ -41,5 +41,8 @@ Header Files + + Header Files + \ No newline at end of file diff --git a/cxplat/src/cxplat_winkernel/size_winkernel.c b/cxplat/src/cxplat_winkernel/size_winkernel.c new file mode 100644 index 0000000..c0f67a8 --- /dev/null +++ b/cxplat/src/cxplat_winkernel/size_winkernel.c @@ -0,0 +1,27 @@ +// Copyright (c) Microsoft Corporation +// SPDX-License-Identifier: MIT +#include "cxplat.h" +#include + +_Must_inspect_result_ cxplat_status_t +cxplat_safe_size_t_multiply( + size_t multiplicand, size_t multiplier, _Out_ _Deref_out_range_(==, multiplicand* multiplier) size_t* result) +{ + return RtlSizeTMult(multiplicand, multiplier, result) == STATUS_SUCCESS ? CXPLAT_STATUS_SUCCESS + : CXPLAT_STATUS_ARITHMETIC_OVERFLOW; +} + +_Must_inspect_result_ cxplat_status_t +cxplat_safe_size_t_add(size_t augend, size_t addend, _Out_ _Deref_out_range_(==, augend + addend) size_t* result) +{ + return RtlSizeTAdd(augend, addend, result) == STATUS_SUCCESS ? CXPLAT_STATUS_SUCCESS + : CXPLAT_STATUS_ARITHMETIC_OVERFLOW; +} + +_Must_inspect_result_ cxplat_status_t +cxplat_safe_size_t_subtract( + size_t minuend, size_t subtrahend, _Out_ _Deref_out_range_(==, minuend - subtrahend) size_t* result) +{ + return RtlSizeTSub(minuend, subtrahend, result) == STATUS_SUCCESS ? CXPLAT_STATUS_SUCCESS + : CXPLAT_STATUS_ARITHMETIC_OVERFLOW; +} \ No newline at end of file diff --git a/cxplat/src/cxplat_winuser/cxplat_winuser.vcxproj b/cxplat/src/cxplat_winuser/cxplat_winuser.vcxproj index 08d6c2e..c4f9561 100644 --- a/cxplat/src/cxplat_winuser/cxplat_winuser.vcxproj +++ b/cxplat/src/cxplat_winuser/cxplat_winuser.vcxproj @@ -143,6 +143,7 @@ + @@ -155,6 +156,7 @@ + diff --git a/cxplat/src/cxplat_winuser/cxplat_winuser.vcxproj.filters b/cxplat/src/cxplat_winuser/cxplat_winuser.vcxproj.filters index edbbdd2..7227551 100644 --- a/cxplat/src/cxplat_winuser/cxplat_winuser.vcxproj.filters +++ b/cxplat/src/cxplat_winuser/cxplat_winuser.vcxproj.filters @@ -42,6 +42,9 @@ Header Files + + Header Files + @@ -59,5 +62,8 @@ Source Files + + Source Files + \ No newline at end of file diff --git a/cxplat/src/cxplat_winuser/size_winuser.c b/cxplat/src/cxplat_winuser/size_winuser.c new file mode 100644 index 0000000..7f17876 --- /dev/null +++ b/cxplat/src/cxplat_winuser/size_winuser.c @@ -0,0 +1,25 @@ +// Copyright (c) Microsoft Corporation +// SPDX-License-Identifier: MIT +#include "cxplat.h" +#include + +_Must_inspect_result_ cxplat_status_t +cxplat_safe_size_t_multiply( + size_t multiplicand, size_t multiplier, _Out_ _Deref_out_range_(==, multiplicand* multiplier) size_t* result) +{ + return SUCCEEDED(SizeTMult(multiplicand, multiplier, result)) ? CXPLAT_STATUS_SUCCESS + : CXPLAT_STATUS_ARITHMETIC_OVERFLOW; +} + +_Must_inspect_result_ cxplat_status_t +cxplat_safe_size_t_add(size_t augend, size_t addend, _Out_ _Deref_out_range_(==, augend + addend) size_t* result) +{ + return SUCCEEDED(SizeTAdd(augend, addend, result)) ? CXPLAT_STATUS_SUCCESS : CXPLAT_STATUS_ARITHMETIC_OVERFLOW; +} + +_Must_inspect_result_ cxplat_status_t +cxplat_safe_size_t_subtract( + size_t minuend, size_t subtrahend, _Out_ _Deref_out_range_(==, minuend - subtrahend) size_t* result) +{ + return SUCCEEDED(SizeTSub(minuend, subtrahend, result)) ? CXPLAT_STATUS_SUCCESS : CXPLAT_STATUS_ARITHMETIC_OVERFLOW; +} \ No newline at end of file