/* * 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 #include #include #include "internal/common.h" #include "internal/safe_math.h" #include #include OSSL_SAFE_MATH_UNSIGNED(size_t, size_t) /* * 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 ossl_inline ossl_unused 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 ossl_inline ossl_unused 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 ossl_inline ossl_unused 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); } /* * Check the result of num and size multiplication for overflow * and set error if it is the case; return true if there was no overflow, * false if there was. */ static ossl_inline ossl_unused bool ossl_size_mul(const size_t num, const size_t size, size_t *bytes, const char *const file, const int line) { int err = 0; *bytes = safe_mul_size_t(num, size, &err); if (ossl_unlikely(err != 0)) { ossl_report_alloc_err_of(file, line); return false; } return true; } /* * Check the result of size1 and size2 addition for overflow * and set error if it is the case; returns true if there was no overflow, * false if there was. */ static ossl_inline ossl_unused bool ossl_size_add(const size_t size1, const size_t size2, size_t *bytes, const char *const file, const int line) { int err = 0; *bytes = safe_add_size_t(size1, size2, &err); if (ossl_unlikely(err != 0)) { ossl_report_alloc_err_of(file, line); return false; } return true; } #endif /* OSSL_INTERNAL_CHECK_SIZE_OVERFLOW_H */