audk/MdePkg/Library/BaseSafeIntLib/SafeIntLib32.c

556 lines
18 KiB
C
Raw Normal View History

MdePkg/BaseSafeIntLib: Add SafeIntLib class and instance https://bugzilla.tianocore.org/show_bug.cgi?id=798 SafeIntLib provides helper functions to prevent integer overflow during type conversion, addition, subtraction, and multiplication. Conversion Functions ==================== * Converting from a signed type to an unsigned type of the same size, or vice-versa. * Converting to a smaller type that could possibly overflow. * Converting from a signed type to a larger unsigned type. Unsigned Addition, Subtraction, Multiplication =============================================== * Unsigned integer math functions protect from overflow and underflow (in case of subtraction). Signed Addition, Subtraction, Multiplication ============================================ * Strongly consider using unsigned numbers. * Signed numbers are often used where unsigned numbers should be used. For example file sizes and array indices should always be unsigned. Subtracting a larger positive signed number from a smaller positive signed number with SafeInt32Sub() will succeed, producing a negative number, that then must not be used as an array index (but can occasionally be used as a pointer index.) Similarly for adding a larger magnitude negative number to a smaller magnitude positive number. * SafeIntLib does not protect you from such errors. It tells you if your integer operations overflowed, not if you are doing the right thing with your non-overflowed integers. * Likewise you can overflow a buffer with a non-overflowed unsigned index. Based on content from the following branch/commits: https://github.com/Microsoft/MS_UEFI/tree/share/MsCapsuleSupport https://github.com/Microsoft/MS_UEFI/commit/21ef3a321c907b40fa93797619c9f6c686dd92e0 https://github.com/Microsoft/MS_UEFI/commit/ca516b1a61315c2d823f453e12d2135098f53d61 https://github.com/Microsoft/MS_UEFI/commit/33bab4031a417d7d5a7d356c15a14c2e60302b2d Cc: Sean Brogan <sean.brogan@microsoft.com> Cc: Jiewen Yao <jiewen.yao@intel.com> Cc: Liming Gao <liming.gao@intel.com> Contributed-under: TianoCore Contribution Agreement 1.1 Signed-off-by: Michael D Kinney <michael.d.kinney@intel.com> Reviewed-by: Sean Brogan <sean.brogan@microsoft.com> Reviewed-by: Liming Gao <liming.gao@intel.com>
2017-04-25 01:37:20 +02:00
/** @file
This library provides helper functions to prevent integer overflow during
type conversion, addition, subtraction, and multiplication.
Copyright (c) 2017, Microsoft Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**/
#include <Base.h>
#include <Library/SafeIntLib.h>
#include <Library/BaseLib.h>
MdePkg/BaseSafeIntLib: Add SafeIntLib class and instance https://bugzilla.tianocore.org/show_bug.cgi?id=798 SafeIntLib provides helper functions to prevent integer overflow during type conversion, addition, subtraction, and multiplication. Conversion Functions ==================== * Converting from a signed type to an unsigned type of the same size, or vice-versa. * Converting to a smaller type that could possibly overflow. * Converting from a signed type to a larger unsigned type. Unsigned Addition, Subtraction, Multiplication =============================================== * Unsigned integer math functions protect from overflow and underflow (in case of subtraction). Signed Addition, Subtraction, Multiplication ============================================ * Strongly consider using unsigned numbers. * Signed numbers are often used where unsigned numbers should be used. For example file sizes and array indices should always be unsigned. Subtracting a larger positive signed number from a smaller positive signed number with SafeInt32Sub() will succeed, producing a negative number, that then must not be used as an array index (but can occasionally be used as a pointer index.) Similarly for adding a larger magnitude negative number to a smaller magnitude positive number. * SafeIntLib does not protect you from such errors. It tells you if your integer operations overflowed, not if you are doing the right thing with your non-overflowed integers. * Likewise you can overflow a buffer with a non-overflowed unsigned index. Based on content from the following branch/commits: https://github.com/Microsoft/MS_UEFI/tree/share/MsCapsuleSupport https://github.com/Microsoft/MS_UEFI/commit/21ef3a321c907b40fa93797619c9f6c686dd92e0 https://github.com/Microsoft/MS_UEFI/commit/ca516b1a61315c2d823f453e12d2135098f53d61 https://github.com/Microsoft/MS_UEFI/commit/33bab4031a417d7d5a7d356c15a14c2e60302b2d Cc: Sean Brogan <sean.brogan@microsoft.com> Cc: Jiewen Yao <jiewen.yao@intel.com> Cc: Liming Gao <liming.gao@intel.com> Contributed-under: TianoCore Contribution Agreement 1.1 Signed-off-by: Michael D Kinney <michael.d.kinney@intel.com> Reviewed-by: Sean Brogan <sean.brogan@microsoft.com> Reviewed-by: Liming Gao <liming.gao@intel.com>
2017-04-25 01:37:20 +02:00
/**
INT32 -> UINTN conversion
Converts the value specified by Operand to a value specified by Result type
and stores the converted value into the caller allocated output buffer
specified by Result. The caller must pass in a Result buffer that is at
least as large as the Result type.
If Result is NULL, RETURN_INVALID_PARAMETER is returned.
If the conversion results in an overflow or an underflow condition, then
Result is set to UINTN_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
@param[in] Operand Operand to be converted to new type
@param[out] Result Pointer to the result of conversion
@retval RETURN_SUCCESS Successful conversion
@retval RETURN_BUFFER_TOO_SMALL Overflow
@retval RETURN_INVALID_PARAMETER Result is NULL
**/
RETURN_STATUS
EFIAPI
SafeInt32ToUintn (
IN INT32 Operand,
OUT UINTN *Result
)
{
return SafeInt32ToUint32 (Operand, (UINT32 *)Result);
}
/**
UINT32 -> INTN conversion
Converts the value specified by Operand to a value specified by Result type
and stores the converted value into the caller allocated output buffer
specified by Result. The caller must pass in a Result buffer that is at
least as large as the Result type.
If Result is NULL, RETURN_INVALID_PARAMETER is returned.
If the conversion results in an overflow or an underflow condition, then
Result is set to INTN_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
@param[in] Operand Operand to be converted to new type
@param[out] Result Pointer to the result of conversion
@retval RETURN_SUCCESS Successful conversion
@retval RETURN_BUFFER_TOO_SMALL Overflow
@retval RETURN_INVALID_PARAMETER Result is NULL
**/
RETURN_STATUS
EFIAPI
SafeUint32ToIntn (
IN UINT32 Operand,
OUT INTN *Result
)
{
return SafeUint32ToInt32 (Operand, (INT32 *)Result);
}
/**
INTN -> INT32 conversion
Converts the value specified by Operand to a value specified by Result type
and stores the converted value into the caller allocated output buffer
specified by Result. The caller must pass in a Result buffer that is at
least as large as the Result type.
If Result is NULL, RETURN_INVALID_PARAMETER is returned.
If the conversion results in an overflow or an underflow condition, then
Result is set to INT32_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
@param[in] Operand Operand to be converted to new type
@param[out] Result Pointer to the result of conversion
@retval RETURN_SUCCESS Successful conversion
@retval RETURN_BUFFER_TOO_SMALL Overflow
@retval RETURN_INVALID_PARAMETER Result is NULL
**/
RETURN_STATUS
EFIAPI
SafeIntnToInt32 (
IN INTN Operand,
OUT INT32 *Result
)
{
if (Result == NULL) {
return RETURN_INVALID_PARAMETER;
}
*Result = (INT32)Operand;
return RETURN_SUCCESS;
}
/**
INTN -> UINT32 conversion
Converts the value specified by Operand to a value specified by Result type
and stores the converted value into the caller allocated output buffer
specified by Result. The caller must pass in a Result buffer that is at
least as large as the Result type.
If Result is NULL, RETURN_INVALID_PARAMETER is returned.
If the conversion results in an overflow or an underflow condition, then
Result is set to UINT32_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
@param[in] Operand Operand to be converted to new type
@param[out] Result Pointer to the result of conversion
@retval RETURN_SUCCESS Successful conversion
@retval RETURN_BUFFER_TOO_SMALL Overflow
@retval RETURN_INVALID_PARAMETER Result is NULL
**/
RETURN_STATUS
EFIAPI
SafeIntnToUint32 (
IN INTN Operand,
OUT UINT32 *Result
)
{
RETURN_STATUS Status;
if (Result == NULL) {
return RETURN_INVALID_PARAMETER;
}
if (Operand >= 0) {
*Result = (UINT32)Operand;
Status = RETURN_SUCCESS;
} else {
*Result = UINT32_ERROR;
Status = RETURN_BUFFER_TOO_SMALL;
}
return Status;
}
/**
UINTN -> UINT32 conversion
Converts the value specified by Operand to a value specified by Result type
and stores the converted value into the caller allocated output buffer
specified by Result. The caller must pass in a Result buffer that is at
least as large as the Result type.
If Result is NULL, RETURN_INVALID_PARAMETER is returned.
If the conversion results in an overflow or an underflow condition, then
Result is set to UINT32_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
@param[in] Operand Operand to be converted to new type
@param[out] Result Pointer to the result of conversion
@retval RETURN_SUCCESS Successful conversion
@retval RETURN_BUFFER_TOO_SMALL Overflow
@retval RETURN_INVALID_PARAMETER Result is NULL
**/
RETURN_STATUS
EFIAPI
SafeUintnToUint32 (
IN UINTN Operand,
OUT UINT32 *Result
)
{
if (Result == NULL) {
return RETURN_INVALID_PARAMETER;
}
*Result = (UINT32)Operand;
return RETURN_SUCCESS;
}
/**
UINTN -> INT64 conversion
Converts the value specified by Operand to a value specified by Result type
and stores the converted value into the caller allocated output buffer
specified by Result. The caller must pass in a Result buffer that is at
least as large as the Result type.
If Result is NULL, RETURN_INVALID_PARAMETER is returned.
If the conversion results in an overflow or an underflow condition, then
Result is set to INT64_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
@param[in] Operand Operand to be converted to new type
@param[out] Result Pointer to the result of conversion
@retval RETURN_SUCCESS Successful conversion
@retval RETURN_BUFFER_TOO_SMALL Overflow
@retval RETURN_INVALID_PARAMETER Result is NULL
**/
RETURN_STATUS
EFIAPI
SafeUintnToInt64 (
IN UINTN Operand,
OUT INT64 *Result
)
{
if (Result == NULL) {
return RETURN_INVALID_PARAMETER;
}
*Result = (INT64)Operand;
return RETURN_SUCCESS;
}
/**
INT64 -> INTN conversion
Converts the value specified by Operand to a value specified by Result type
and stores the converted value into the caller allocated output buffer
specified by Result. The caller must pass in a Result buffer that is at
least as large as the Result type.
If Result is NULL, RETURN_INVALID_PARAMETER is returned.
If the conversion results in an overflow or an underflow condition, then
Result is set to INTN_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
@param[in] Operand Operand to be converted to new type
@param[out] Result Pointer to the result of conversion
@retval RETURN_SUCCESS Successful conversion
@retval RETURN_BUFFER_TOO_SMALL Overflow
@retval RETURN_INVALID_PARAMETER Result is NULL
**/
RETURN_STATUS
EFIAPI
SafeInt64ToIntn (
IN INT64 Operand,
OUT INTN *Result
)
{
return SafeInt64ToInt32 (Operand, (INT32 *)Result);
}
/**
INT64 -> UINTN conversion
Converts the value specified by Operand to a value specified by Result type
and stores the converted value into the caller allocated output buffer
specified by Result. The caller must pass in a Result buffer that is at
least as large as the Result type.
If Result is NULL, RETURN_INVALID_PARAMETER is returned.
If the conversion results in an overflow or an underflow condition, then
Result is set to UINTN_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
@param[in] Operand Operand to be converted to new type
@param[out] Result Pointer to the result of conversion
@retval RETURN_SUCCESS Successful conversion
@retval RETURN_BUFFER_TOO_SMALL Overflow
@retval RETURN_INVALID_PARAMETER Result is NULL
**/
RETURN_STATUS
EFIAPI
SafeInt64ToUintn (
IN INT64 Operand,
OUT UINTN *Result
)
{
return SafeInt64ToUint32 (Operand, (UINT32 *)Result);
}
/**
UINT64 -> UINTN conversion
Converts the value specified by Operand to a value specified by Result type
and stores the converted value into the caller allocated output buffer
specified by Result. The caller must pass in a Result buffer that is at
least as large as the Result type.
If Result is NULL, RETURN_INVALID_PARAMETER is returned.
If the conversion results in an overflow or an underflow condition, then
Result is set to UINTN_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
@param[in] Operand Operand to be converted to new type
@param[out] Result Pointer to the result of conversion
@retval RETURN_SUCCESS Successful conversion
@retval RETURN_BUFFER_TOO_SMALL Overflow
@retval RETURN_INVALID_PARAMETER Result is NULL
**/
RETURN_STATUS
EFIAPI
SafeUint64ToUintn (
IN UINT64 Operand,
OUT UINTN *Result
)
{
return SafeUint64ToUint32 ((UINT64) Operand, (UINT32 *)Result);
}
/**
UINTN addition
Performs the requested operation using the input parameters into a value
specified by Result type and stores the converted value into the caller
allocated output buffer specified by Result. The caller must pass in a
Result buffer that is at least as large as the Result type.
If Result is NULL, RETURN_INVALID_PARAMETER is returned.
If the requested operation results in an overflow or an underflow condition,
then Result is set to UINTN_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
@param[in] Augend A number to which addend will be added
@param[in] Addend A number to be added to another
@param[out] Result Pointer to the result of addition
@retval RETURN_SUCCESS Successful addition
@retval RETURN_BUFFER_TOO_SMALL Overflow
@retval RETURN_INVALID_PARAMETER Result is NULL
**/
RETURN_STATUS
EFIAPI
SafeUintnAdd (
IN UINTN Augend,
IN UINTN Addend,
OUT UINTN *Result
)
{
RETURN_STATUS Status;
if (Result == NULL) {
return RETURN_INVALID_PARAMETER;
}
if ((Augend + Addend) >= Augend) {
*Result = (Augend + Addend);
Status = RETURN_SUCCESS;
} else {
*Result = UINTN_ERROR;
Status = RETURN_BUFFER_TOO_SMALL;
}
return Status;
}
/**
UINTN subtraction
Performs the requested operation using the input parameters into a value
specified by Result type and stores the converted value into the caller
allocated output buffer specified by Result. The caller must pass in a
Result buffer that is at least as large as the Result type.
If Result is NULL, RETURN_INVALID_PARAMETER is returned.
If the requested operation results in an overflow or an underflow condition,
then Result is set to UINTN_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
@param[in] Minuend A number from which another is to be subtracted.
@param[in] Subtrahend A number to be subtracted from another
@param[out] Result Pointer to the result of subtraction
@retval RETURN_SUCCESS Successful subtraction
@retval RETURN_BUFFER_TOO_SMALL Underflow
@retval RETURN_INVALID_PARAMETER Result is NULL
**/
RETURN_STATUS
EFIAPI
SafeUintnSub (
IN UINTN Minuend,
IN UINTN Subtrahend,
OUT UINTN *Result
)
{
RETURN_STATUS Status;
if (Result == NULL) {
return RETURN_INVALID_PARAMETER;
}
if (Minuend >= Subtrahend) {
*Result = (Minuend - Subtrahend);
Status = RETURN_SUCCESS;
} else {
*Result = UINTN_ERROR;
Status = RETURN_BUFFER_TOO_SMALL;
}
return Status;
}
/**
UINTN multiplication
Performs the requested operation using the input parameters into a value
specified by Result type and stores the converted value into the caller
allocated output buffer specified by Result. The caller must pass in a
Result buffer that is at least as large as the Result type.
If Result is NULL, RETURN_INVALID_PARAMETER is returned.
If the requested operation results in an overflow or an underflow condition,
then Result is set to UINTN_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
@param[in] Multiplicand A number that is to be multiplied by another
@param[in] Multiplier A number by which the multiplicand is to be multiplied
@param[out] Result Pointer to the result of multiplication
@retval RETURN_SUCCESS Successful multiplication
@retval RETURN_BUFFER_TOO_SMALL Overflow
@retval RETURN_INVALID_PARAMETER Result is NULL
**/
RETURN_STATUS
EFIAPI
SafeUintnMult (
IN UINTN Multiplicand,
IN UINTN Multiplier,
OUT UINTN *Result
)
{
UINT64 IntermediateResult;
IntermediateResult = ((UINT64) Multiplicand) *((UINT64) Multiplier);
return SafeUint64ToUintn (IntermediateResult, Result);
}
/**
INTN Addition
Performs the requested operation using the input parameters into a value
specified by Result type and stores the converted value into the caller
allocated output buffer specified by Result. The caller must pass in a
Result buffer that is at least as large as the Result type.
If Result is NULL, RETURN_INVALID_PARAMETER is returned.
If the requested operation results in an overflow or an underflow condition,
then Result is set to INTN_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
@param[in] Augend A number to which addend will be added
@param[in] Addend A number to be added to another
@param[out] Result Pointer to the result of addition
@retval RETURN_SUCCESS Successful addition
@retval RETURN_BUFFER_TOO_SMALL Overflow
@retval RETURN_INVALID_PARAMETER Result is NULL
**/
RETURN_STATUS
EFIAPI
SafeIntnAdd (
IN INTN Augend,
IN INTN Addend,
OUT INTN *Result
)
{
return SafeInt64ToIntn (((INT64)Augend) + ((INT64)Addend), Result);
}
/**
INTN Subtraction
Performs the requested operation using the input parameters into a value
specified by Result type and stores the converted value into the caller
allocated output buffer specified by Result. The caller must pass in a
Result buffer that is at least as large as the Result type.
If Result is NULL, RETURN_INVALID_PARAMETER is returned.
If the requested operation results in an overflow or an underflow condition,
then Result is set to INTN_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
@param[in] Minuend A number from which another is to be subtracted.
@param[in] Subtrahend A number to be subtracted from another
@param[out] Result Pointer to the result of subtraction
@retval RETURN_SUCCESS Successful subtraction
@retval RETURN_BUFFER_TOO_SMALL Underflow
@retval RETURN_INVALID_PARAMETER Result is NULL
**/
RETURN_STATUS
EFIAPI
SafeIntnSub (
IN INTN Minuend,
IN INTN Subtrahend,
OUT INTN *Result
)
{
return SafeInt64ToIntn (((INT64)Minuend) - ((INT64)Subtrahend), Result);
}
/**
INTN multiplication
Performs the requested operation using the input parameters into a value
specified by Result type and stores the converted value into the caller
allocated output buffer specified by Result. The caller must pass in a
Result buffer that is at least as large as the Result type.
If Result is NULL, RETURN_INVALID_PARAMETER is returned.
If the requested operation results in an overflow or an underflow condition,
then Result is set to INTN_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
@param[in] Multiplicand A number that is to be multiplied by another
@param[in] Multiplier A number by which the multiplicand is to be multiplied
@param[out] Result Pointer to the result of multiplication
@retval RETURN_SUCCESS Successful multiplication
@retval RETURN_BUFFER_TOO_SMALL Overflow
@retval RETURN_INVALID_PARAMETER Result is NULL
**/
RETURN_STATUS
EFIAPI
SafeIntnMult (
IN INTN Multiplicand,
IN INTN Multiplier,
OUT INTN *Result
)
{
return SafeInt64ToIntn (MultS64x64 (Multiplicand, Multiplier), Result);
MdePkg/BaseSafeIntLib: Add SafeIntLib class and instance https://bugzilla.tianocore.org/show_bug.cgi?id=798 SafeIntLib provides helper functions to prevent integer overflow during type conversion, addition, subtraction, and multiplication. Conversion Functions ==================== * Converting from a signed type to an unsigned type of the same size, or vice-versa. * Converting to a smaller type that could possibly overflow. * Converting from a signed type to a larger unsigned type. Unsigned Addition, Subtraction, Multiplication =============================================== * Unsigned integer math functions protect from overflow and underflow (in case of subtraction). Signed Addition, Subtraction, Multiplication ============================================ * Strongly consider using unsigned numbers. * Signed numbers are often used where unsigned numbers should be used. For example file sizes and array indices should always be unsigned. Subtracting a larger positive signed number from a smaller positive signed number with SafeInt32Sub() will succeed, producing a negative number, that then must not be used as an array index (but can occasionally be used as a pointer index.) Similarly for adding a larger magnitude negative number to a smaller magnitude positive number. * SafeIntLib does not protect you from such errors. It tells you if your integer operations overflowed, not if you are doing the right thing with your non-overflowed integers. * Likewise you can overflow a buffer with a non-overflowed unsigned index. Based on content from the following branch/commits: https://github.com/Microsoft/MS_UEFI/tree/share/MsCapsuleSupport https://github.com/Microsoft/MS_UEFI/commit/21ef3a321c907b40fa93797619c9f6c686dd92e0 https://github.com/Microsoft/MS_UEFI/commit/ca516b1a61315c2d823f453e12d2135098f53d61 https://github.com/Microsoft/MS_UEFI/commit/33bab4031a417d7d5a7d356c15a14c2e60302b2d Cc: Sean Brogan <sean.brogan@microsoft.com> Cc: Jiewen Yao <jiewen.yao@intel.com> Cc: Liming Gao <liming.gao@intel.com> Contributed-under: TianoCore Contribution Agreement 1.1 Signed-off-by: Michael D Kinney <michael.d.kinney@intel.com> Reviewed-by: Sean Brogan <sean.brogan@microsoft.com> Reviewed-by: Liming Gao <liming.gao@intel.com>
2017-04-25 01:37:20 +02:00
}