mirror of https://github.com/openssl/openssl.git
114 lines
3.2 KiB
C
114 lines
3.2 KiB
C
/*
|
|
* Copyright 2025 The OpenSSL Project Authors. All Rights Reserved.
|
|
*
|
|
* Licensed under the Apache License 2.0 (the "License"). You may not use
|
|
* this file except in compliance with the License. You can obtain a copy
|
|
* in the file LICENSE in the source distribution or at
|
|
* https://www.openssl.org/source/license.html
|
|
*/
|
|
|
|
/*
|
|
* Utility overflow checking and reporting functions
|
|
*/
|
|
|
|
#ifndef OSSL_INTERNAL_CHECK_SIZE_OVERFLOW_H
|
|
# define OSSL_INTERNAL_CHECK_SIZE_OVERFLOW_H
|
|
|
|
# include <limits.h>
|
|
# include <stdbool.h>
|
|
# include <stdint.h>
|
|
|
|
# include "internal/common.h"
|
|
|
|
# include <openssl/cryptoerr.h>
|
|
# include <openssl/err.h>
|
|
|
|
/*
|
|
* A helper routine to report memory allocation errors.
|
|
* Similar to the ERR_raise() macro, but accepts explicit file/line arguments,
|
|
* pre-defines the library to ERR_LIB_CRYPTO, and avoids emitting an error
|
|
* if both file set to NULL and line set to 0.
|
|
*/
|
|
static ossl_inline ossl_unused void
|
|
ossl_report_alloc_err_ex(const char * const file, const int line,
|
|
const int reason)
|
|
{
|
|
/*
|
|
* ossl_err_get_state_int() in err.c uses CRYPTO_zalloc(num, NULL, 0) for
|
|
* ERR_STATE allocation. Prevent mem alloc error loop while reporting error.
|
|
*/
|
|
if (file != NULL || line != 0) {
|
|
ERR_new();
|
|
ERR_set_debug(file, line, NULL);
|
|
ERR_set_error(ERR_LIB_CRYPTO, reason, NULL);
|
|
}
|
|
}
|
|
|
|
/* Report a memory allocation failure. */
|
|
static inline void
|
|
ossl_report_alloc_err(const char * const file, const int line)
|
|
{
|
|
ossl_report_alloc_err_ex(file, line, ERR_R_MALLOC_FAILURE);
|
|
}
|
|
|
|
/* Report an integer overflow during allocation size calculation. */
|
|
static inline void
|
|
ossl_report_alloc_err_of(const char * const file, const int line)
|
|
{
|
|
ossl_report_alloc_err_ex(file, line, CRYPTO_R_INTEGER_OVERFLOW);
|
|
}
|
|
|
|
/* Report invalid memory allocation call arguments. */
|
|
static inline void
|
|
ossl_report_alloc_err_inv(const char * const file, const int line)
|
|
{
|
|
ossl_report_alloc_err_ex(file, line, ERR_R_PASSED_INVALID_ARGUMENT);
|
|
}
|
|
|
|
/*
|
|
* A small (premature) optimisation: do not check for multiplication overflow
|
|
* if neither of the operands is at least half the type size.
|
|
*/
|
|
# define SQRT_SIZE_T ((size_t) 1 << (sizeof(size_t) * (CHAR_BIT / 2)))
|
|
|
|
/*
|
|
* Check the result of num and size multiplication for overflow
|
|
* and set error if it is the case.
|
|
*/
|
|
static ossl_inline ossl_unused bool
|
|
ossl_size_mul_of(const size_t num, const size_t size, size_t *bytes,
|
|
const char * const file, const int line)
|
|
{
|
|
*bytes = num * size;
|
|
|
|
if (ossl_unlikely(((num | size) >= SQRT_SIZE_T)
|
|
&& size && ((*bytes / size) != num))) {
|
|
ossl_report_alloc_err_of(file, line);
|
|
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
/*
|
|
* Check the result of size1 and size2 addition for overflow
|
|
* and set error if it is the case.
|
|
*/
|
|
static ossl_inline ossl_unused bool
|
|
ossl_size_add_of(const size_t size1, const size_t size2, size_t *bytes,
|
|
const char * const file, const int line)
|
|
{
|
|
*bytes = size1 + size2;
|
|
|
|
if (ossl_unlikely(*bytes < size1)) {
|
|
ossl_report_alloc_err_of(file, line);
|
|
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
#endif /* OSSL_INTERNAL_CHECK_SIZE_OVERFLOW_H */
|