From a14b8541e377b704e03749400fb1f235fd326016 Mon Sep 17 00:00:00 2001 From: owent Date: Thu, 14 May 2026 18:02:21 +0800 Subject: [PATCH 1/2] =?UTF-8?q?=E4=BC=98=E5=8C=96=E7=AE=97=E6=B3=95?= =?UTF-8?q?=E5=BA=93=E7=9A=84=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .clang-tidy | 2 + include/algorithm/compression.h | 2 - include/algorithm/sha.h | 7 +- src/algorithm/base64.cpp | 121 +++++++------ src/algorithm/compression.cpp | 100 ++++++++--- src/algorithm/crc.cpp | 36 ++-- src/algorithm/crypto_cipher.cpp | 294 ++++++++++++++++++++------------ src/algorithm/crypto_dh.cpp | 96 ++++++----- src/algorithm/crypto_hmac.cpp | 40 ++++- src/algorithm/murmur_hash.cpp | 261 +++++++++++++++++----------- src/algorithm/sha.cpp | 244 ++++++++++++++------------ src/algorithm/xxtea.cpp | 54 +++--- test/case/murmur_hash_test.cpp | 63 +++++++ 13 files changed, 824 insertions(+), 496 deletions(-) diff --git a/.clang-tidy b/.clang-tidy index bab8b859..d15e6087 100644 --- a/.clang-tidy +++ b/.clang-tidy @@ -51,6 +51,7 @@ Checks: # 过于常见的用法而忽略 - "-bugprone-easily-swappable-parameters" # 参数容易被隐式转换而被调用者传错顺序 - "-misc-no-recursion" # 递归调用 + - "-misc-include-cleaner" # 包含清理,某些头文件互相依赖时容易被误判 - "-performance-move-const-arg" # 无意义的move可用于标记生命周期 - "-cppcoreguidelines-pro-type-const-cast" # 使用const_cast的地方通常都是故意使用的 - "-modernize-use-nodiscard" @@ -64,6 +65,7 @@ Checks: - "-modernize-use-ranges" - "-modernize-use-starts-ends-with" - "-readability-use-anyofallof" + - "-readability-use-concise-preprocessor-directives" # 以下检查由于性能问题被关闭(@see https://github.com/llvm/llvm-project/blob/main/clang-tools-extra/clangd/TidyFastChecks.inc) - "-misc-confusable-identifiers" - "-misc-const-correctness" diff --git a/include/algorithm/compression.h b/include/algorithm/compression.h index ad7433d9..e8b7fde1 100644 --- a/include/algorithm/compression.h +++ b/include/algorithm/compression.h @@ -36,7 +36,6 @@ # include # include -# include # include ATFRAMEWORK_UTILS_NAMESPACE_BEGIN @@ -149,4 +148,3 @@ ATFRAMEWORK_UTILS_NAMESPACE_END #endif // ATFW_UTIL_MACRO_COMPRESSION_ENABLED #endif // UTIL_ALGORITHM_COMPRESSION_H - diff --git a/include/algorithm/sha.h b/include/algorithm/sha.h index 27393371..33502f1e 100644 --- a/include/algorithm/sha.h +++ b/include/algorithm/sha.h @@ -58,12 +58,12 @@ class sha { ATFRAMEWORK_UTILS_API sha(); ATFRAMEWORK_UTILS_API ~sha(); - ATFRAMEWORK_UTILS_API sha(sha&&); - ATFRAMEWORK_UTILS_API sha& operator=(sha&&); + ATFRAMEWORK_UTILS_API sha(sha&&) noexcept; + ATFRAMEWORK_UTILS_API sha& operator=(sha&&) noexcept; ATFRAMEWORK_UTILS_API bool init(type); ATFRAMEWORK_UTILS_API void close(); - ATFRAMEWORK_UTILS_API void swap(sha& other); + ATFRAMEWORK_UTILS_API void swap(sha& other) noexcept; ATFRAMEWORK_UTILS_API bool update(const unsigned char* in, size_t inlen); ATFRAMEWORK_UTILS_API bool final(); @@ -95,4 +95,3 @@ class sha { ATFRAMEWORK_UTILS_NAMESPACE_END #endif - diff --git a/src/algorithm/base64.cpp b/src/algorithm/base64.cpp index 0639e758..c643fe68 100644 --- a/src/algorithm/base64.cpp +++ b/src/algorithm/base64.cpp @@ -1,20 +1,22 @@ // Copyright 2026 atframework -#include -#include -#include -#include -#include -#include +// Project namespace/API macros are provided by the public header and are intentionally used through it here. +// NOLINTBEGIN(misc-include-cleaner) + +#include +#include +#include +#include +#include #include "algorithm/base64.h" -#define BASE64_SIZE_T_MAX ((size_t)-1) /* SIZE_T_MAX is not standard */ -#define BASE64_INVALID_CHARACTER -0x002C /**< Invalid character in input. */ +#define BASE64_SIZE_T_MAX ((size_t)-1) /* SIZE_T_MAX is not standard */ +#define BASE64_INVALID_CHARACTER (-0x002C) /**< Invalid character in input. */ ATFRAMEWORK_UTILS_NAMESPACE_BEGIN -namespace detail { +namespace { using base_enc_map_t = const unsigned char[64]; using base_dec_map_t = const unsigned char[128]; static base_enc_map_t base64_enc_map_basic = { @@ -56,15 +58,26 @@ static constexpr const unsigned char base64_dec_map_url[128] = { 23, 24, 25, 127, 127, 127, 127, 63, 127, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 127, 127, 127, 127, 127}; +static inline char *get_writable_string_data(std::string &value) noexcept { + if (value.empty()) { + return nullptr; + } +#if (defined(_MSVC_LANG) && _MSVC_LANG >= 201703L) || __cplusplus >= 201703L + return value.data(); +#else + return &value[0]; // NOLINT(cppcoreguidelines-pro-bounds-constant-array-index,modernize-use-data) +#endif +} + static int base64_encode_inner(unsigned char *dst, size_t dlen, size_t *olen, const unsigned char *src, size_t slen, base_enc_map_t &base64_enc_map, unsigned char padding_char) { - size_t i, n, nopadding; - int C1, C2, C3; - unsigned char *p; + size_t i = 0, n = 0, nopadding = 0; + int C1 = 0, C2 = 0, C3 = 0; + unsigned char *p = nullptr; if (slen == 0) { *olen = 0; - return (0); + return 0; } n = (slen + 2) / 3; @@ -123,7 +136,7 @@ static int base64_encode_inner(unsigned char *dst, size_t dlen, size_t *olen, co *olen = static_cast(p - dst); *p = 0; - return (0); + return 0; } static inline int base64_encode_inner(std::string &dst, const unsigned char *src, size_t slen, @@ -136,8 +149,8 @@ static inline int base64_encode_inner(std::string &dst, const unsigned char *src return 0; } - int ret = base64_encode_inner(reinterpret_cast(&dst[0]), dst.size(), &olen, src, slen, - base64_enc_map, padding_char); + int ret = base64_encode_inner(reinterpret_cast(get_writable_string_data(dst)), dst.size(), &olen, + src, slen, base64_enc_map, padding_char); assert(0 != ret || dst.size() == olen + 1); // pop back last zero if (!dst.empty() && *dst.rbegin() == 0) { @@ -154,10 +167,10 @@ static inline int base64_encode_inner(std::string &dst, const std::string &in, b static int base64_decode_inner(unsigned char *dst, size_t dlen, size_t *olen, const unsigned char *src, size_t slen, base_dec_map_t &base64_dec_map, unsigned char padding_char) { - size_t i, n; - size_t j, x; - size_t valid_slen, line_len; - unsigned char *p; + size_t i = 0, n = 0; + size_t j = 0, x = 0; + size_t valid_slen = 0, line_len = 0; + unsigned char *p = nullptr; /* First pass: check for validity and get output length */ for (i = n = j = valid_slen = line_len = 0; i < slen; i++) { @@ -169,7 +182,9 @@ static int base64_decode_inner(unsigned char *dst, size_t dlen, size_t *olen, co } /* Spaces at end of buffer are OK */ - if (i == slen) break; + if (i == slen) { + break; + } if (src[i] == '\r' || src[i] == '\n') { line_len = 0; @@ -177,29 +192,36 @@ static int base64_decode_inner(unsigned char *dst, size_t dlen, size_t *olen, co } /* Space inside a line is an error */ - if (x != 0 && line_len != 0) return -2; + if (x != 0 && line_len != 0) { + return -2; + } ++valid_slen; ++line_len; if (src[i] == padding_char) { if (++j > 2) { return -2; - } else if ((valid_slen & 3) == 1 || (valid_slen & 3) == 2) { + } + if ((valid_slen & 3) == 1 || (valid_slen & 3) == 2) { // First and second char of every group can not be padding char return -2; } } else { - if (src[i] > 127 || base64_dec_map[src[i]] == 127) return -2; + if (src[i] > 127 || base64_dec_map[src[i]] == 127) { + return -2; + } } - if (base64_dec_map[src[i]] < 64 && j != 0) return -2; + if (base64_dec_map[src[i]] < 64 && j != 0) { + return -2; + } n++; } if (n == 0) { *olen = 0; - return (0); + return 0; } // no padding, add j to padding length @@ -212,7 +234,7 @@ static int base64_decode_inner(unsigned char *dst, size_t dlen, size_t *olen, co * risk of integer overflow in n: * n = ( ( n * 6 ) + 7 ) >> 3; */ - n = (6 * (n >> 3)) + ((6 * (n & 0x7) + 7) >> 3); + n = (6 * (n >> 3)) + (((6 * (n & 0x7)) + 7) >> 3); n -= j; if (dst == nullptr || dlen < n) { @@ -221,30 +243,34 @@ static int base64_decode_inner(unsigned char *dst, size_t dlen, size_t *olen, co } for (n = x = 0, p = dst; i > 0; i--, src++) { - if (*src == '\r' || *src == '\n' || *src == ' ' || *src == '\t') continue; - if (*src == padding_char) continue; + if (*src == '\r' || *src == '\n' || *src == ' ' || *src == '\t') { + continue; + } + if (*src == padding_char) { + continue; + } x = (x << 6) | (base64_dec_map[*src] & 0x3F); if (++n == 4) { n = 0; - *p++ = (unsigned char)(x >> 16); - *p++ = (unsigned char)(x >> 8); - *p++ = (unsigned char)(x); + *p++ = static_cast(x >> 16); + *p++ = static_cast(x >> 8); + *p++ = static_cast(x); } } // no padding, the tail code if (n == 2) { - *p++ = (unsigned char)(x >> 4); + *p++ = static_cast(x >> 4); } else if (n == 3) { - *p++ = (unsigned char)(x >> 10); - *p++ = (unsigned char)(x >> 2); + *p++ = static_cast(x >> 10); + *p++ = static_cast(x >> 2); } *olen = static_cast(p - dst); - return (0); + return 0; } static inline int base64_decode_inner(std::string &dst, const unsigned char *src, size_t slen, @@ -260,8 +286,8 @@ static inline int base64_decode_inner(std::string &dst, const unsigned char *src } dst.resize(olen); - int ret = base64_decode_inner(reinterpret_cast(&dst[0]), dst.size(), &olen, src, slen, - base64_dec_map, padding_char); + int ret = base64_decode_inner(reinterpret_cast(get_writable_string_data(dst)), dst.size(), &olen, + src, slen, base64_dec_map, padding_char); assert(0 != ret || olen == dst.size()); return ret; } @@ -320,39 +346,36 @@ static inline unsigned char base64_get_padding_char(base64_mode_t::type mode) { return '='; } } -} // namespace detail +} // namespace ATFRAMEWORK_UTILS_API int base64_encode(unsigned char *dst, size_t dlen, size_t *olen, const unsigned char *src, size_t slen, base64_mode_t::type mode) { - return detail::base64_encode_inner(dst, dlen, olen, src, slen, detail::base64_get_enc_map(mode), - detail::base64_get_padding_char(mode)); + return base64_encode_inner(dst, dlen, olen, src, slen, base64_get_enc_map(mode), base64_get_padding_char(mode)); } ATFRAMEWORK_UTILS_API int base64_encode(std::string &dst, const unsigned char *src, size_t slen, base64_mode_t::type mode) { - return detail::base64_encode_inner(dst, src, slen, detail::base64_get_enc_map(mode), - detail::base64_get_padding_char(mode)); + return base64_encode_inner(dst, src, slen, base64_get_enc_map(mode), base64_get_padding_char(mode)); } ATFRAMEWORK_UTILS_API int base64_encode(std::string &dst, const std::string &in, base64_mode_t::type mode) { - return detail::base64_encode_inner(dst, in, detail::base64_get_enc_map(mode), detail::base64_get_padding_char(mode)); + return base64_encode_inner(dst, in, base64_get_enc_map(mode), base64_get_padding_char(mode)); } ATFRAMEWORK_UTILS_API int base64_decode(unsigned char *dst, size_t dlen, size_t *olen, const unsigned char *src, size_t slen, base64_mode_t::type mode) { - return detail::base64_decode_inner(dst, dlen, olen, src, slen, detail::base64_get_dec_map(mode), - detail::base64_get_padding_char(mode)); + return base64_decode_inner(dst, dlen, olen, src, slen, base64_get_dec_map(mode), base64_get_padding_char(mode)); } ATFRAMEWORK_UTILS_API int base64_decode(std::string &dst, const unsigned char *src, size_t slen, base64_mode_t::type mode) { - return detail::base64_decode_inner(dst, src, slen, detail::base64_get_dec_map(mode), - detail::base64_get_padding_char(mode)); + return base64_decode_inner(dst, src, slen, base64_get_dec_map(mode), base64_get_padding_char(mode)); } ATFRAMEWORK_UTILS_API int base64_decode(std::string &dst, const std::string &in, base64_mode_t::type mode) { - return detail::base64_decode_inner(dst, in, detail::base64_get_dec_map(mode), detail::base64_get_padding_char(mode)); + return base64_decode_inner(dst, in, base64_get_dec_map(mode), base64_get_padding_char(mode)); } ATFRAMEWORK_UTILS_NAMESPACE_END +// NOLINTEND(misc-include-cleaner) diff --git a/src/algorithm/compression.cpp b/src/algorithm/compression.cpp index 4503ba37..a63a3ff9 100644 --- a/src/algorithm/compression.cpp +++ b/src/algorithm/compression.cpp @@ -2,11 +2,14 @@ // // Created by owent on 2026.01.20 +// Compression backend headers are selected by project feature macros, which makes include-cleaner and concise +// preprocessor checks noisy in this compatibility file. +// NOLINTBEGIN(misc-include-cleaner,modernize-use-designated-initializers,readability-use-concise-preprocessor-directives) + #include "algorithm/compression.h" #ifdef ATFW_UTIL_MACRO_COMPRESSION_ENABLED -# include # include # include @@ -32,8 +35,23 @@ namespace compression { namespace { +template +static constexpr T _numeric_limits_max() noexcept { + return (std::numeric_limits::max)(); // NOLINT(readability-redundant-parentheses) +} + +static bool _resize_output(std::vector& output, size_t size) noexcept { + try { + output.resize(size); + return true; + } catch (...) { + output.clear(); + return false; + } +} + static bool _size_to_int(size_t input, int& output) noexcept { - if (input > static_cast((std::numeric_limits::max)())) { + if (input > static_cast(_numeric_limits_max())) { return false; } output = static_cast(input); @@ -42,7 +60,7 @@ static bool _size_to_int(size_t input, int& output) noexcept { # if defined(ATFW_UTIL_MACRO_COMPRESSION_ZLIB) static bool _size_to_ulongf(size_t input, uLongf& output) noexcept { - if (input > static_cast((std::numeric_limits::max)())) { + if (input > static_cast(_numeric_limits_max())) { return false; } output = static_cast(input); @@ -161,14 +179,18 @@ static int _compress_internal(algorithm_t type, gsl::span i if (bound == 0) { return error_code_t::kOperation; } - output.resize(bound); + if (!_resize_output(output, bound)) { + return error_code_t::kOperation; + } int zstd_level = use_raw_level ? raw_level : _map_level_zstd(level); size_t ret = ZSTD_compress(output.data(), output.size(), input.data(), input.size(), zstd_level); if (ZSTD_isError(ret)) { output.clear(); return error_code_t::kOperation; } - output.resize(ret); + if (!_resize_output(output, ret)) { + return error_code_t::kOperation; + } return error_code_t::kOk; # else return error_code_t::kNotSupport; @@ -186,7 +208,9 @@ static int _compress_internal(algorithm_t type, gsl::span i if (bound <= 0) { return error_code_t::kOperation; } - output.resize(static_cast(bound)); + if (!_resize_output(output, static_cast(bound))) { + return error_code_t::kOperation; + } int result_size = 0; if (use_raw_level) { @@ -222,7 +246,9 @@ static int _compress_internal(algorithm_t type, gsl::span i output.clear(); return error_code_t::kOperation; } - output.resize(static_cast(result_size)); + if (!_resize_output(output, static_cast(result_size))) { + return error_code_t::kOperation; + } return error_code_t::kOk; # else return error_code_t::kNotSupport; @@ -235,7 +261,9 @@ static int _compress_internal(algorithm_t type, gsl::span i return error_code_t::kNotSupport; } size_t max_len = snappy_max_compressed_length(input.size()); - output.resize(max_len); + if (!_resize_output(output, max_len)) { + return error_code_t::kOperation; + } size_t output_len = max_len; snappy_status status = snappy_compress(reinterpret_cast(input.data()), input.size(), reinterpret_cast(output.data()), &output_len); @@ -243,7 +271,9 @@ static int _compress_internal(algorithm_t type, gsl::span i output.clear(); return error_code_t::kOperation; } - output.resize(output_len); + if (!_resize_output(output, output_len)) { + return error_code_t::kOperation; + } return error_code_t::kOk; # else return error_code_t::kNotSupport; @@ -253,7 +283,7 @@ static int _compress_internal(algorithm_t type, gsl::span i case algorithm_t::kZlib: { # if defined(ATFW_UTIL_MACRO_COMPRESSION_ZLIB) uLong input_size = 0; - if (input.size() > static_cast((std::numeric_limits::max)())) { + if (input.size() > static_cast(_numeric_limits_max())) { return error_code_t::kInvalidParam; } input_size = static_cast(input.size()); @@ -261,7 +291,9 @@ static int _compress_internal(algorithm_t type, gsl::span i if (!_size_to_ulongf(static_cast(compressBound(input_size)), dest_len)) { return error_code_t::kInvalidParam; } - output.resize(static_cast(dest_len)); + if (!_resize_output(output, static_cast(dest_len))) { + return error_code_t::kOperation; + } int zlib_level = use_raw_level ? raw_level : _map_level_zlib(level); int zret = compress2(reinterpret_cast(output.data()), &dest_len, reinterpret_cast(input.data()), input_size, zlib_level); @@ -269,7 +301,9 @@ static int _compress_internal(algorithm_t type, gsl::span i output.clear(); return error_code_t::kOperation; } - output.resize(static_cast(dest_len)); + if (!_resize_output(output, static_cast(dest_len))) { + return error_code_t::kOperation; + } return error_code_t::kOk; # else return error_code_t::kNotSupport; @@ -318,18 +352,23 @@ ATFRAMEWORK_UTILS_API bool is_algorithm_supported(algorithm_t type) noexcept { ATFRAMEWORK_UTILS_API std::vector get_supported_algorithms() noexcept { std::vector result; + try { + result.reserve(4); # if defined(ATFW_UTIL_MACRO_COMPRESSION_ZSTD) - result.push_back(algorithm_t::kZstd); + result.push_back(algorithm_t::kZstd); # endif # if defined(ATFW_UTIL_MACRO_COMPRESSION_LZ4) - result.push_back(algorithm_t::kLz4); + result.push_back(algorithm_t::kLz4); # endif # if defined(ATFW_UTIL_MACRO_COMPRESSION_SNAPPY) - result.push_back(algorithm_t::kSnappy); + result.push_back(algorithm_t::kSnappy); # endif # if defined(ATFW_UTIL_MACRO_COMPRESSION_ZLIB) - result.push_back(algorithm_t::kZlib); + result.push_back(algorithm_t::kZlib); # endif + } catch (...) { + result.clear(); + } return result; } @@ -394,13 +433,17 @@ ATFRAMEWORK_UTILS_API int decompress(algorithm_t type, gsl::span(frame_size); } - output.resize(expect_size); + if (!_resize_output(output, expect_size)) { + return error_code_t::kOperation; + } size_t ret = ZSTD_decompress(output.data(), output.size(), input.data(), input.size()); if (ZSTD_isError(ret)) { output.clear(); return error_code_t::kOperation; } - output.resize(ret); + if (!_resize_output(output, ret)) { + return error_code_t::kOperation; + } return error_code_t::kOk; # else return error_code_t::kNotSupport; @@ -419,7 +462,9 @@ ATFRAMEWORK_UTILS_API int decompress(algorithm_t type, gsl::span(input.data()), reinterpret_cast(output.data()), input_size, output_size); if (ret < 0) { @@ -445,14 +490,18 @@ ATFRAMEWORK_UTILS_API int decompress(algorithm_t type, gsl::span(input.data()), input.size(), reinterpret_cast(output.data()), &expect_size); if (status != SNAPPY_OK) { output.clear(); return error_code_t::kOperation; } - output.resize(expect_size); + if (!_resize_output(output, expect_size)) { + return error_code_t::kOperation; + } return error_code_t::kOk; # else return error_code_t::kNotSupport; @@ -468,14 +517,18 @@ ATFRAMEWORK_UTILS_API int decompress(algorithm_t type, gsl::span(output.data()), &dest_len, reinterpret_cast(input.data()), static_cast(input.size())); if (zret != Z_OK) { output.clear(); return error_code_t::kOperation; } - output.resize(static_cast(dest_len)); + if (!_resize_output(output, static_cast(dest_len))) { + return error_code_t::kOperation; + } return error_code_t::kOk; # else return error_code_t::kNotSupport; @@ -493,3 +546,4 @@ ATFRAMEWORK_UTILS_NAMESPACE_END #endif // ATFW_UTIL_MACRO_COMPRESSION_ENABLED +// NOLINTEND(misc-include-cleaner,modernize-use-designated-initializers,readability-use-concise-preprocessor-directives) diff --git a/src/algorithm/crc.cpp b/src/algorithm/crc.cpp index c72df594..8a42c558 100644 --- a/src/algorithm/crc.cpp +++ b/src/algorithm/crc.cpp @@ -1,15 +1,17 @@ // Copyright 2026 atframework -#include -#include -#include -#include -#include +// Namespace/API macros are provided by the public header and intentionally used through it here. +// NOLINTBEGIN(misc-include-cleaner) + +#include +#include +#include +#include #include "algorithm/crc.h" ATFRAMEWORK_UTILS_NAMESPACE_BEGIN -namespace detail { +namespace { /* CRC16 implementation according to CCITT standards. * @@ -172,44 +174,46 @@ static constexpr const uint64_t crc64_tab[256] = { UINT64_C(0x29b7d047efec8728), }; -} // namespace detail +} // namespace ATFRAMEWORK_UTILS_API uint16_t crc16(const unsigned char *s, size_t l, uint16_t init_val) { - if (!s) { + if (s == nullptr) { return init_val; } - size_t j; + size_t j = 0; for (j = 0; j < l; ++j) { unsigned char byte = s[j]; - init_val = static_cast(init_val << 8) ^ detail::crc16_tab[((init_val >> 8) ^ (uint16_t)byte) & 0x00FF]; + init_val = + static_cast(init_val << 8) ^ crc16_tab[((init_val >> 8) ^ static_cast(byte)) & 0x00FF]; } return init_val; } ATFRAMEWORK_UTILS_API uint32_t crc32(const unsigned char *s, size_t l, uint32_t init_val) { - if (!s) { + if (s == nullptr) { return init_val; } - size_t j; + size_t j = 0; for (j = 0; j < l; ++j) { unsigned char byte = s[j]; - init_val = detail::crc32_tab[static_cast(init_val) ^ (uint32_t)byte] ^ (init_val >> 8); + init_val = crc32_tab[static_cast(init_val) ^ static_cast(byte)] ^ (init_val >> 8); } return init_val; } ATFRAMEWORK_UTILS_API uint64_t crc64(const unsigned char *s, size_t l, uint64_t init_val) { - if (!s) { + if (s == nullptr) { return init_val; } - size_t j; + size_t j = 0; for (j = 0; j < l; ++j) { unsigned char byte = s[j]; - init_val = detail::crc64_tab[static_cast(init_val) ^ (uint64_t)byte] ^ (init_val >> 8); + init_val = crc64_tab[static_cast(init_val) ^ static_cast(byte)] ^ (init_val >> 8); } return init_val; } ATFRAMEWORK_UTILS_NAMESPACE_END +// NOLINTEND(misc-include-cleaner) diff --git a/src/algorithm/crypto_cipher.cpp b/src/algorithm/crypto_cipher.cpp index 69135f4c..f008f287 100644 --- a/src/algorithm/crypto_cipher.cpp +++ b/src/algorithm/crypto_cipher.cpp @@ -2,15 +2,25 @@ // // Create by owent +// Crypto backend headers/functions are selected through feature macros, so include-cleaner and concise-preprocessor +// checks produce noisy false positives in this compatibility-heavy file. +// NOLINTBEGIN(misc-include-cleaner,readability-use-concise-preprocessor-directives) + #include "algorithm/crypto_cipher.h" +#include + #include #include #include #include +#include #include +#include +#include +#include #ifdef ATFW_UTIL_MACRO_CRYPTO_CIPHER_ENABLED @@ -18,20 +28,23 @@ # include # define LIBSODIUM_BLOCK_SIZE 64 +namespace { using libsodium_counter_t = uint64_t; # define LIBSODIUM_COUNTER_SIZE sizeof(libsodium_counter_t) static inline libsodium_counter_t libsodium_get_block(const unsigned char *p) { - return static_cast(((uint32_t)(p)[0]) | (((uint32_t)(p)[1]) << 8) | (((uint32_t)p[2]) << 16) | - (((uint32_t)(p)[3]) << 24)); + return static_cast(static_cast(p[0]) | (static_cast(p[1]) << 8) | + (static_cast(p[2]) << 16) | (static_cast(p[3]) << 24)); } static inline libsodium_counter_t libsodium_get_counter(const unsigned char *iv) { - uint32_t low = static_cast(libsodium_get_block(iv)); - uint32_t high = static_cast(libsodium_get_block(iv + 4)); - return static_cast((((libsodium_counter_t)(high)) << 32) | low); + const uint32_t low = static_cast(libsodium_get_block(iv)); + const uint32_t high = static_cast(libsodium_get_block(iv + 4)); + return static_cast((static_cast(high) << 32) | low); } +} // namespace + # endif /** @@ -50,7 +63,7 @@ static inline libsodium_counter_t libsodium_get_counter(const unsigned char *iv) # if defined(ATFRAMEWORK_UTILS_CRYPTO_USE_OPENSSL) || defined(ATFRAMEWORK_UTILS_CRYPTO_USE_LIBRESSL) || \ defined(ATFRAMEWORK_UTILS_CRYPTO_USE_BORINGSSL) -# if defined(LIBRESSL_VERSION_NUMBER) +# ifdef LIBRESSL_VERSION_NUMBER # if LIBRESSL_VERSION_NUMBER > 0x2040000fL # define CRYPTO_USE_CHACHA20_WITH_CIPHER @@ -94,44 +107,88 @@ static inline libsodium_counter_t libsodium_get_counter(const unsigned char *iv) ATFRAMEWORK_UTILS_NAMESPACE_BEGIN namespace crypto { -enum cipher_interface_method_t { - EN_CIMT_INVALID = 0, // inner - EN_CIMT_XXTEA = 1, // inner - EN_CIMT_INNER, // inner bound - EN_CIMT_CIPHER, // using openssl/libressl/boringssl/mbedtls - EN_CIMT_LIBSODIUM, // using libsodium - EN_CIMT_LIBSODIUM_CHACHA20, - EN_CIMT_LIBSODIUM_CHACHA20_IETF, - EN_CIMT_LIBSODIUM_XCHACHA20, // imported in libsodium 1.0.12 or upper - EN_CIMT_LIBSODIUM_SALSA20, - EN_CIMT_LIBSODIUM_XSALSA20, // imported in libsodium 1.0.12 or upper - EN_CIMT_LIBSODIUM_CHACHA20_POLY1305, - EN_CIMT_LIBSODIUM_CHACHA20_POLY1305_IETF, - EN_CIMT_LIBSODIUM_XCHACHA20_POLY1305_IETF, // imported in libsodium 1.0.12 or upper +namespace { +enum class cipher_interface_method_t : int32_t { + kInvalid = 0, // inner + kXxtea = 1, // inner + kInnerBound = 2, // inner bound + kCipher = 3, // using openssl/libressl/boringssl/mbedtls + kLibsodium = 4, // using libsodium + kLibsodiumChacha20 = 5, + kLibsodiumChacha20Ietf = 6, + kLibsodiumXchacha20 = 7, // imported in libsodium 1.0.12 or upper + kLibsodiumSalsa20 = 8, + kLibsodiumXsalsa20 = 9, // imported in libsodium 1.0.12 or upper + kLibsodiumChacha20Poly1305 = 10, + kLibsodiumChacha20Poly1305Ietf = 11, + kLibsodiumXchacha20Poly1305Ietf = 12, // imported in libsodium 1.0.12 or upper }; -enum cipher_interface_flags_t { - EN_CIFT_NONE = 0, // using inner algorithm - EN_CIFT_NO_FINISH = 0x0001, // should not call finish after update - EN_CIFT_AEAD = 0x0010, // is aead cipher - EN_CIFT_VARIABLE_IV_LEN = 0x0020, // can be variable iv length - EN_CIFT_AEAD_SET_LENGTH_BEFORE = 0x0040, // call update to set length before update - EN_CIFT_DECRYPT_NO_PADDING = 0x0100, // set no padding when decrypt - EN_CIFT_ENCRYPT_NO_PADDING = 0x0200, // set no padding when encrypt +enum class cipher_interface_flags_t : int32_t { + kNone = 0x0000, // using inner algorithm + kNoFinish = 0x0001, // should not call finish after update + kAead = 0x0010, // is aead cipher + kVariableIvLen = 0x0020, // can be variable iv length + kAeadSetLengthBefore = 0x0040, // call update to set length before update + kDecryptNoPadding = 0x0100, // set no padding when decrypt + kEncryptNoPadding = 0x0200, // set no padding when encrypt }; +constexpr cipher_interface_method_t EN_CIMT_INVALID = cipher_interface_method_t::kInvalid; +constexpr cipher_interface_method_t EN_CIMT_XXTEA = cipher_interface_method_t::kXxtea; +constexpr cipher_interface_method_t EN_CIMT_INNER = cipher_interface_method_t::kInnerBound; +constexpr cipher_interface_method_t EN_CIMT_CIPHER = cipher_interface_method_t::kCipher; +constexpr cipher_interface_method_t EN_CIMT_LIBSODIUM = cipher_interface_method_t::kLibsodium; +constexpr cipher_interface_method_t EN_CIMT_LIBSODIUM_CHACHA20 = cipher_interface_method_t::kLibsodiumChacha20; +constexpr cipher_interface_method_t EN_CIMT_LIBSODIUM_CHACHA20_IETF = cipher_interface_method_t::kLibsodiumChacha20Ietf; +constexpr cipher_interface_method_t EN_CIMT_LIBSODIUM_XCHACHA20 = cipher_interface_method_t::kLibsodiumXchacha20; +constexpr cipher_interface_method_t EN_CIMT_LIBSODIUM_SALSA20 = cipher_interface_method_t::kLibsodiumSalsa20; +constexpr cipher_interface_method_t EN_CIMT_LIBSODIUM_XSALSA20 = cipher_interface_method_t::kLibsodiumXsalsa20; +constexpr cipher_interface_method_t EN_CIMT_LIBSODIUM_CHACHA20_POLY1305 = + cipher_interface_method_t::kLibsodiumChacha20Poly1305; +constexpr cipher_interface_method_t EN_CIMT_LIBSODIUM_CHACHA20_POLY1305_IETF = + cipher_interface_method_t::kLibsodiumChacha20Poly1305Ietf; +constexpr cipher_interface_method_t EN_CIMT_LIBSODIUM_XCHACHA20_POLY1305_IETF = + cipher_interface_method_t::kLibsodiumXchacha20Poly1305Ietf; + +constexpr uint32_t EN_CIFT_NONE = static_cast(cipher_interface_flags_t::kNone); +constexpr uint32_t EN_CIFT_NO_FINISH = static_cast(cipher_interface_flags_t::kNoFinish); +constexpr uint32_t EN_CIFT_AEAD = static_cast(cipher_interface_flags_t::kAead); +constexpr uint32_t EN_CIFT_VARIABLE_IV_LEN = static_cast(cipher_interface_flags_t::kVariableIvLen); +constexpr uint32_t EN_CIFT_AEAD_SET_LENGTH_BEFORE = + static_cast(cipher_interface_flags_t::kAeadSetLengthBefore); +constexpr uint32_t EN_CIFT_DECRYPT_NO_PADDING = static_cast(cipher_interface_flags_t::kDecryptNoPadding); +constexpr uint32_t EN_CIFT_ENCRYPT_NO_PADDING = static_cast(cipher_interface_flags_t::kEncryptNoPadding); + +static constexpr uint32_t to_underlying(cipher_interface_flags_t value) noexcept { + return static_cast(value); +} +} // namespace + struct cipher_interface_info_t { + constexpr cipher_interface_info_t(const char *in_name, cipher_interface_method_t in_method, + const char *in_openssl_name, const char *in_mbedtls_name, + uint32_t in_flags) noexcept + : name(in_name), + openssl_name(in_openssl_name), + mbedtls_name(in_mbedtls_name), + method(in_method), + flags(in_flags) {} + const char *name; - cipher_interface_method_t method; const char *openssl_name; const char *mbedtls_name; + cipher_interface_method_t method; uint32_t flags; }; namespace { # if defined(ATFRAMEWORK_UTILS_CRYPTO_USE_OPENSSL) || defined(ATFRAMEWORK_UTILS_CRYPTO_USE_LIBRESSL) || \ defined(ATFRAMEWORK_UTILS_CRYPTO_USE_BORINGSSL) -ATFRAMEWORK_UTILS_NAMESPACE_ID::lock::atomic_int_type g_global_init_counter_(0); +static inline ATFRAMEWORK_UTILS_NAMESPACE_ID::lock::atomic_int_type &get_global_init_counter() { + static ATFRAMEWORK_UTILS_NAMESPACE_ID::lock::atomic_int_type counter(0); + return counter; +} # endif static inline int setup_errorno(cipher &ci, int64_t err, cipher::error_code_t ret) { ci.set_last_errno(err); @@ -145,13 +202,13 @@ static inline void iv_shift_append(std::vector &iv, const unsigne const size_t iv_len = iv.size(); if (clen >= iv_len) { - memcpy(&iv[0], ciphertext + (clen - iv_len), iv_len); + memcpy(iv.data(), ciphertext + (clen - iv_len), iv_len); return; } // new_iv = last(iv_old || ciphertext) - memmove(&iv[0], &iv[0] + clen, iv_len - clen); - memcpy(&iv[iv_len - clen], ciphertext, clen); + memmove(iv.data(), iv.data() + clen, iv_len - clen); + memcpy(iv.data() + (iv_len - clen), ciphertext, clen); } static inline void increment_iv_be(std::vector &iv, uint64_t add) { @@ -159,19 +216,20 @@ static inline void increment_iv_be(std::vector &iv, uint64_t add) return; } + unsigned char *iv_data = iv.data(); size_t i = iv.size(); while (i > 0 && add > 0) { --i; - uint64_t sum = static_cast(iv[i]) + (add & 0xFFu); - iv[i] = static_cast(sum & 0xFFu); + uint64_t sum = static_cast(iv_data[i]) + (add & 0xFFu); + iv_data[i] = static_cast(sum & 0xFFu); add = (add >> 8) + (sum >> 8); } // propagate remaining carry if any while (i > 0 && add > 0) { --i; - uint64_t sum = static_cast(iv[i]) + (add & 0xFFu); - iv[i] = static_cast(sum & 0xFFu); + uint64_t sum = static_cast(iv_data[i]) + (add & 0xFFu); + iv_data[i] = static_cast(sum & 0xFFu); add = (add >> 8) + (sum >> 8); } } @@ -181,7 +239,7 @@ static inline cipher::iv_roll_policy_t compute_iv_roll_policy(const cipher_inter return cipher::IV_ROLL_NONE; } - if (0 != (interface->flags & static_cast(cipher_interface_flags_t::EN_CIFT_AEAD))) { + if (0 != (interface->flags & to_underlying(cipher_interface_flags_t::kAead))) { return cipher::IV_ROLL_AEAD_INC1_BE; } @@ -251,13 +309,14 @@ static inline void roll_iv_after_success(cipher::iv_roll_policy_t policy, std::v return; } + unsigned char *iv_data = iv.data(); uint64_t counter = 0; for (size_t i = 0; i < 8; ++i) { - counter |= (static_cast(iv[i]) << (8 * i)); + counter |= (static_cast(iv_data[i]) << (8 * i)); } counter += blocks; for (size_t i = 0; i < 8; ++i) { - iv[i] = static_cast((counter >> (8 * i)) & 0xFFu); + iv_data[i] = static_cast((counter >> (8 * i)) & 0xFFu); } return; } @@ -354,7 +413,7 @@ static constexpr const cipher_interface_info_t __g_supported_ciphers[] = { # endif - {nullptr, EN_CIMT_INVALID, nullptr, nullptr, false}, // end + {nullptr, EN_CIMT_INVALID, nullptr, nullptr, EN_CIFT_NONE}, // end }; static const cipher_interface_info_t *get_cipher_interface_by_name(nostd::string_view name) { @@ -434,7 +493,7 @@ ATFRAMEWORK_UTILS_API int cipher::init(nostd::string_view name, int32_t mode) { if (static_cast(error_code_t::kOk) == ret) { interface_ = interface; - if (0 != (interface_->flags & static_cast(cipher_interface_flags_t::EN_CIFT_AEAD))) { + if (0 != (interface_->flags & to_underlying(cipher_interface_flags_t::kAead))) { tag_length_ = 16; } iv_roll_policy_ = compute_iv_roll_policy(interface_); @@ -865,13 +924,13 @@ ATFRAMEWORK_UTILS_API int cipher::set_key(const unsigned char *key, uint32_t key if (nullptr != cipher_context_.enc) { if (!EVP_CipherInit_ex(cipher_context_.enc, nullptr, nullptr, key, nullptr, -1)) { - res = (int)ERR_peek_error(); + res = static_cast(ERR_peek_error()); } } if (nullptr != cipher_context_.dec) { if (!EVP_CipherInit_ex(cipher_context_.dec, nullptr, nullptr, key, nullptr, -1)) { - res = (int)ERR_peek_error(); + res = static_cast(ERR_peek_error()); } } @@ -1016,7 +1075,7 @@ ATFRAMEWORK_UTILS_API int cipher::encrypt(const unsigned char *input, size_t ile // OpenSSL接入采用新的EVP接口 if (!iv_.empty()) { - if (!EVP_CipherInit_ex(cipher_context_.enc, nullptr, nullptr, nullptr, &iv_[0], -1)) { + if (!EVP_CipherInit_ex(cipher_context_.enc, nullptr, nullptr, nullptr, iv_.data(), -1)) { return setup_errorno(*this, static_cast(ERR_peek_error()), error_code_t::kCipherOperationSetIv); } } @@ -1059,7 +1118,7 @@ ATFRAMEWORK_UTILS_API int cipher::encrypt(const unsigned char *input, size_t ile } unsigned char empty_iv[MBEDTLS_MAX_IV_LENGTH] = {0}; - last_errorno_ = mbedtls_cipher_crypt(cipher_context_.enc, iv_.empty() ? empty_iv : &iv_[0], iv_.size(), input, + last_errorno_ = mbedtls_cipher_crypt(cipher_context_.enc, iv_.empty() ? empty_iv : iv_.data(), iv_.size(), input, ilen, output, olen); if (last_errorno_ != 0) { return static_cast(error_code_t::kCipherOperation); @@ -1074,9 +1133,9 @@ ATFRAMEWORK_UTILS_API int cipher::encrypt(const unsigned char *input, size_t ile # if defined(ATFRAMEWORK_UTILS_CRYPTO_USE_LIBSODIUM) && ATFRAMEWORK_UTILS_CRYPTO_USE_LIBSODIUM // CHACHA20系算法使用 libsodium 接入 case EN_CIMT_LIBSODIUM_CHACHA20: - last_errorno_ = - crypto_stream_chacha20_xor_ic(output, input, ilen, &iv_[LIBSODIUM_COUNTER_SIZE], - static_cast(libsodium_get_counter(&iv_[0])), libsodium_context_.key); + last_errorno_ = crypto_stream_chacha20_xor_ic(output, input, ilen, iv_.data() + LIBSODIUM_COUNTER_SIZE, + static_cast(libsodium_get_counter(iv_.data())), + libsodium_context_.key); if (last_errorno_ != 0) { return static_cast(error_code_t::kLibsodiumOperation); } @@ -1086,8 +1145,8 @@ ATFRAMEWORK_UTILS_API int cipher::encrypt(const unsigned char *input, size_t ile } return static_cast(error_code_t::kOk); case EN_CIMT_LIBSODIUM_CHACHA20_IETF: - last_errorno_ = crypto_stream_chacha20_ietf_xor_ic(output, input, ilen, &iv_[LIBSODIUM_COUNTER_SIZE], - static_cast(libsodium_get_counter(&iv_[0])), + last_errorno_ = crypto_stream_chacha20_ietf_xor_ic(output, input, ilen, iv_.data() + LIBSODIUM_COUNTER_SIZE, + static_cast(libsodium_get_counter(iv_.data())), libsodium_context_.key); if (last_errorno_ != 0) { return static_cast(error_code_t::kLibsodiumOperation); @@ -1099,9 +1158,10 @@ ATFRAMEWORK_UTILS_API int cipher::encrypt(const unsigned char *input, size_t ile return static_cast(error_code_t::kOk); # ifdef crypto_stream_xchacha20_KEYBYTES - last_errorno_ = - crypto_stream_xchacha20_xor_ic(output, input, ilen, &iv_[LIBSODIUM_COUNTER_SIZE], - static_cast(libsodium_get_counter(&iv_[0])), libsodium_context_.key); + case EN_CIMT_LIBSODIUM_XCHACHA20: + last_errorno_ = crypto_stream_xchacha20_xor_ic(output, input, ilen, iv_.data() + LIBSODIUM_COUNTER_SIZE, + static_cast(libsodium_get_counter(iv_.data())), + libsodium_context_.key); if (last_errorno_ != 0) { return static_cast(error_code_t::kLibsodiumOperation); } @@ -1113,9 +1173,9 @@ ATFRAMEWORK_UTILS_API int cipher::encrypt(const unsigned char *input, size_t ile # endif case EN_CIMT_LIBSODIUM_SALSA20: - last_errorno_ = - crypto_stream_salsa20_xor_ic(output, input, ilen, &iv_[LIBSODIUM_COUNTER_SIZE], - static_cast(libsodium_get_counter(&iv_[0])), libsodium_context_.key); + last_errorno_ = crypto_stream_salsa20_xor_ic(output, input, ilen, iv_.data() + LIBSODIUM_COUNTER_SIZE, + static_cast(libsodium_get_counter(iv_.data())), + libsodium_context_.key); if (last_errorno_ != 0) { return static_cast(error_code_t::kLibsodiumOperation); } @@ -1125,9 +1185,9 @@ ATFRAMEWORK_UTILS_API int cipher::encrypt(const unsigned char *input, size_t ile } return static_cast(error_code_t::kOk); case EN_CIMT_LIBSODIUM_XSALSA20: - last_errorno_ = - crypto_stream_xsalsa20_xor_ic(output, input, ilen, &iv_[LIBSODIUM_COUNTER_SIZE], - static_cast(libsodium_get_counter(&iv_[0])), libsodium_context_.key); + last_errorno_ = crypto_stream_xsalsa20_xor_ic(output, input, ilen, iv_.data() + LIBSODIUM_COUNTER_SIZE, + static_cast(libsodium_get_counter(iv_.data())), + libsodium_context_.key); if (last_errorno_ != 0) { return static_cast(error_code_t::kLibsodiumOperation); } @@ -1180,10 +1240,11 @@ ATFRAMEWORK_UTILS_API int cipher::decrypt(const unsigned char *input, size_t ile # if defined(ATFRAMEWORK_UTILS_CRYPTO_USE_OPENSSL) || defined(ATFRAMEWORK_UTILS_CRYPTO_USE_LIBRESSL) || \ defined(ATFRAMEWORK_UTILS_CRYPTO_USE_BORINGSSL) // OpenSSL接入采用新的EVP接口 - int outl, finish_olen; + int outl = 0; + int finish_olen = 0; if (!iv_.empty()) { - if (!EVP_CipherInit_ex(cipher_context_.dec, nullptr, nullptr, nullptr, &iv_[0], -1)) { + if (!EVP_CipherInit_ex(cipher_context_.dec, nullptr, nullptr, nullptr, iv_.data(), -1)) { return setup_errorno(*this, static_cast(ERR_peek_error()), error_code_t::kCipherOperationSetIv); } } @@ -1226,7 +1287,7 @@ ATFRAMEWORK_UTILS_API int cipher::decrypt(const unsigned char *input, size_t ile } unsigned char empty_iv[MBEDTLS_MAX_IV_LENGTH] = {0}; - last_errorno_ = mbedtls_cipher_crypt(cipher_context_.dec, iv_.empty() ? empty_iv : &iv_[0], iv_.size(), input, + last_errorno_ = mbedtls_cipher_crypt(cipher_context_.dec, iv_.empty() ? empty_iv : iv_.data(), iv_.size(), input, ilen, output, olen); if (last_errorno_ != 0) { return static_cast(error_code_t::kCipherOperation); @@ -1241,9 +1302,9 @@ ATFRAMEWORK_UTILS_API int cipher::decrypt(const unsigned char *input, size_t ile # if defined(ATFRAMEWORK_UTILS_CRYPTO_USE_LIBSODIUM) && ATFRAMEWORK_UTILS_CRYPTO_USE_LIBSODIUM // CHACHA20系算法使用 libsodium 接入 case EN_CIMT_LIBSODIUM_CHACHA20: - last_errorno_ = - crypto_stream_chacha20_xor_ic(output, input, ilen, &iv_[LIBSODIUM_COUNTER_SIZE], - static_cast(libsodium_get_counter(&iv_[0])), libsodium_context_.key); + last_errorno_ = crypto_stream_chacha20_xor_ic(output, input, ilen, iv_.data() + LIBSODIUM_COUNTER_SIZE, + static_cast(libsodium_get_counter(iv_.data())), + libsodium_context_.key); if (last_errorno_ != 0) { return static_cast(error_code_t::kLibsodiumOperation); } @@ -1253,8 +1314,8 @@ ATFRAMEWORK_UTILS_API int cipher::decrypt(const unsigned char *input, size_t ile } return static_cast(error_code_t::kOk); case EN_CIMT_LIBSODIUM_CHACHA20_IETF: - last_errorno_ = crypto_stream_chacha20_ietf_xor_ic(output, input, ilen, &iv_[LIBSODIUM_COUNTER_SIZE], - static_cast(libsodium_get_counter(&iv_[0])), + last_errorno_ = crypto_stream_chacha20_ietf_xor_ic(output, input, ilen, iv_.data() + LIBSODIUM_COUNTER_SIZE, + static_cast(libsodium_get_counter(iv_.data())), libsodium_context_.key); if (last_errorno_ != 0) { return static_cast(error_code_t::kLibsodiumOperation); @@ -1266,9 +1327,10 @@ ATFRAMEWORK_UTILS_API int cipher::decrypt(const unsigned char *input, size_t ile return static_cast(error_code_t::kOk); # ifdef crypto_stream_xchacha20_KEYBYTES - last_errorno_ = - crypto_stream_xchacha20_xor_ic(output, input, ilen, &iv_[LIBSODIUM_COUNTER_SIZE], - static_cast(libsodium_get_counter(&iv_[0])), libsodium_context_.key); + case EN_CIMT_LIBSODIUM_XCHACHA20: + last_errorno_ = crypto_stream_xchacha20_xor_ic(output, input, ilen, iv_.data() + LIBSODIUM_COUNTER_SIZE, + static_cast(libsodium_get_counter(iv_.data())), + libsodium_context_.key); if (last_errorno_ != 0) { return static_cast(error_code_t::kLibsodiumOperation); } @@ -1280,9 +1342,9 @@ ATFRAMEWORK_UTILS_API int cipher::decrypt(const unsigned char *input, size_t ile # endif case EN_CIMT_LIBSODIUM_SALSA20: - last_errorno_ = - crypto_stream_salsa20_xor_ic(output, input, ilen, &iv_[LIBSODIUM_COUNTER_SIZE], - static_cast(libsodium_get_counter(&iv_[0])), libsodium_context_.key); + last_errorno_ = crypto_stream_salsa20_xor_ic(output, input, ilen, iv_.data() + LIBSODIUM_COUNTER_SIZE, + static_cast(libsodium_get_counter(iv_.data())), + libsodium_context_.key); if (last_errorno_ != 0) { return static_cast(error_code_t::kLibsodiumOperation); } @@ -1292,9 +1354,9 @@ ATFRAMEWORK_UTILS_API int cipher::decrypt(const unsigned char *input, size_t ile } return static_cast(error_code_t::kOk); case EN_CIMT_LIBSODIUM_XSALSA20: - last_errorno_ = - crypto_stream_xsalsa20_xor_ic(output, input, ilen, &iv_[LIBSODIUM_COUNTER_SIZE], - static_cast(libsodium_get_counter(&iv_[0])), libsodium_context_.key); + last_errorno_ = crypto_stream_xsalsa20_xor_ic(output, input, ilen, iv_.data() + LIBSODIUM_COUNTER_SIZE, + static_cast(libsodium_get_counter(iv_.data())), + libsodium_context_.key); if (last_errorno_ != 0) { return static_cast(error_code_t::kLibsodiumOperation); } @@ -1340,22 +1402,24 @@ ATFRAMEWORK_UTILS_API int cipher::encrypt_aead(const unsigned char *input, size_ # if defined(ATFRAMEWORK_UTILS_CRYPTO_USE_OPENSSL) || defined(ATFRAMEWORK_UTILS_CRYPTO_USE_LIBRESSL) || \ defined(ATFRAMEWORK_UTILS_CRYPTO_USE_BORINGSSL) - int outl, finish_olen; + int outl = 0; + int finish_olen = 0; if (!iv_.empty()) { if (0 != (interface_->flags & EN_CIFT_VARIABLE_IV_LEN)) { - if (!EVP_CIPHER_CTX_ctrl(cipher_context_.enc, EVP_CTRL_AEAD_SET_IVLEN, static_cast(iv_.size()), 0)) { + if (!EVP_CIPHER_CTX_ctrl(cipher_context_.enc, EVP_CTRL_AEAD_SET_IVLEN, static_cast(iv_.size()), + nullptr)) { return setup_errorno(*this, static_cast(ERR_peek_error()), error_code_t::kCipherOperationSetIv); } } - if (!EVP_CipherInit_ex(cipher_context_.enc, nullptr, nullptr, nullptr, &iv_[0], -1)) { + if (!EVP_CipherInit_ex(cipher_context_.enc, nullptr, nullptr, nullptr, iv_.data(), -1)) { return setup_errorno(*this, static_cast(ERR_peek_error()), error_code_t::kCipherOperationSetIv); } } if (0 != (interface_->flags & EN_CIFT_AEAD_SET_LENGTH_BEFORE)) { - int tmplen; + int tmplen = 0; if (!EVP_CipherUpdate(cipher_context_.enc, nullptr, &tmplen, nullptr, static_cast(ilen))) { return setup_errorno(*this, static_cast(ERR_peek_error()), error_code_t::kCipherOperation); } @@ -1413,10 +1477,10 @@ ATFRAMEWORK_UTILS_API int cipher::encrypt_aead(const unsigned char *input, size_ const size_t tag_len = static_cast(tag_length_); last_errorno_ = # if MBEDTLS_VERSION_MAJOR >= 3 - mbedtls_cipher_auth_encrypt_ext(cipher_context_.enc, iv_.empty() ? empty_iv : &iv_[0], iv_.size(), ad, ad_len, - input, ilen, output, *olen, olen, tag_len) + mbedtls_cipher_auth_encrypt_ext(cipher_context_.enc, iv_.empty() ? empty_iv : iv_.data(), iv_.size(), ad, + ad_len, input, ilen, output, *olen, olen, tag_len) # else - mbedtls_cipher_auth_encrypt(cipher_context_.enc, iv_.empty() ? empty_iv : &iv_[0], iv_.size(), ad, ad_len, + mbedtls_cipher_auth_encrypt(cipher_context_.enc, iv_.empty() ? empty_iv : iv_.data(), iv_.size(), ad, ad_len, input, ilen, output, olen, output + ilen, tag_len) # endif ; @@ -1442,8 +1506,8 @@ ATFRAMEWORK_UTILS_API int cipher::encrypt_aead(const unsigned char *input, size_ } unsigned long long maclen = tag_len; // NOLINT: runtime/int - last_errorno_ = crypto_aead_chacha20poly1305_encrypt_detached(output, output + ilen, &maclen, input, ilen, ad, - ad_len, nullptr, &iv_[0], libsodium_context_.key); + last_errorno_ = crypto_aead_chacha20poly1305_encrypt_detached( + output, output + ilen, &maclen, input, ilen, ad, ad_len, nullptr, iv_.data(), libsodium_context_.key); if (last_errorno_ != 0) { return static_cast(error_code_t::kLibsodiumOperation); } @@ -1461,7 +1525,7 @@ ATFRAMEWORK_UTILS_API int cipher::encrypt_aead(const unsigned char *input, size_ unsigned long long maclen = tag_len; // NOLINT: runtime/int last_errorno_ = crypto_aead_chacha20poly1305_ietf_encrypt_detached( - output, output + ilen, &maclen, input, ilen, ad, ad_len, nullptr, &iv_[0], libsodium_context_.key); + output, output + ilen, &maclen, input, ilen, ad, ad_len, nullptr, iv_.data(), libsodium_context_.key); if (last_errorno_ != 0) { return static_cast(error_code_t::kLibsodiumOperation); } @@ -1481,7 +1545,7 @@ ATFRAMEWORK_UTILS_API int cipher::encrypt_aead(const unsigned char *input, size_ unsigned long long maclen = tag_len; // NOLINT: runtime/int last_errorno_ = crypto_aead_xchacha20poly1305_ietf_encrypt_detached( - output, output + ilen, &maclen, input, ilen, ad, ad_len, nullptr, &iv_[0], libsodium_context_.key); + output, output + ilen, &maclen, input, ilen, ad, ad_len, nullptr, iv_.data(), libsodium_context_.key); if (last_errorno_ != 0) { return static_cast(error_code_t::kLibsodiumOperation); } @@ -1532,16 +1596,18 @@ ATFRAMEWORK_UTILS_API int cipher::decrypt_aead(const unsigned char *input, size_ # if defined(ATFRAMEWORK_UTILS_CRYPTO_USE_OPENSSL) || defined(ATFRAMEWORK_UTILS_CRYPTO_USE_LIBRESSL) || \ defined(ATFRAMEWORK_UTILS_CRYPTO_USE_BORINGSSL) - int outl, finish_olen; + int outl = 0; + int finish_olen = 0; if (!iv_.empty()) { if (0 != (interface_->flags & EN_CIFT_VARIABLE_IV_LEN)) { - if (!EVP_CIPHER_CTX_ctrl(cipher_context_.dec, EVP_CTRL_AEAD_SET_IVLEN, static_cast(iv_.size()), 0)) { + if (!EVP_CIPHER_CTX_ctrl(cipher_context_.dec, EVP_CTRL_AEAD_SET_IVLEN, static_cast(iv_.size()), + nullptr)) { return setup_errorno(*this, static_cast(ERR_peek_error()), error_code_t::kCipherOperationSetIv); } } - if (!EVP_CipherInit_ex(cipher_context_.dec, nullptr, nullptr, nullptr, &iv_[0], -1)) { + if (!EVP_CipherInit_ex(cipher_context_.dec, nullptr, nullptr, nullptr, iv_.data(), -1)) { return setup_errorno(*this, static_cast(ERR_peek_error()), error_code_t::kCipherOperationSetIv); } } @@ -1554,7 +1620,7 @@ ATFRAMEWORK_UTILS_API int cipher::decrypt_aead(const unsigned char *input, size_ } if (0 != (interface_->flags & EN_CIFT_AEAD_SET_LENGTH_BEFORE)) { - int tmplen; + int tmplen = 0; if (!EVP_CipherUpdate(cipher_context_.dec, nullptr, &tmplen, nullptr, static_cast(ilen - tag_length_))) { return setup_errorno(*this, static_cast(ERR_peek_error()), error_code_t::kCipherOperation); } @@ -1602,10 +1668,10 @@ ATFRAMEWORK_UTILS_API int cipher::decrypt_aead(const unsigned char *input, size_ const size_t tag_len = static_cast(tag_length_); last_errorno_ = # if MBEDTLS_VERSION_MAJOR >= 3 - mbedtls_cipher_auth_decrypt_ext(cipher_context_.dec, iv_.empty() ? empty_iv : &iv_[0], iv_.size(), ad, ad_len, - input, ilen, output, *olen, olen, tag_len) + mbedtls_cipher_auth_decrypt_ext(cipher_context_.dec, iv_.empty() ? empty_iv : iv_.data(), iv_.size(), ad, + ad_len, input, ilen, output, *olen, olen, tag_len) # else - mbedtls_cipher_auth_decrypt(cipher_context_.dec, iv_.empty() ? empty_iv : &iv_[0], iv_.size(), ad, ad_len, + mbedtls_cipher_auth_decrypt(cipher_context_.dec, iv_.empty() ? empty_iv : iv_.data(), iv_.size(), ad, ad_len, input, ilen, output, olen, input + ilen - tag_len, tag_len) # endif ; @@ -1628,8 +1694,9 @@ ATFRAMEWORK_UTILS_API int cipher::decrypt_aead(const unsigned char *input, size_ return static_cast(error_code_t::kLibsodiumOperationTagLen); } - last_errorno_ = crypto_aead_chacha20poly1305_decrypt_detached( - output, nullptr, input, ilen - tag_len, input + ilen - tag_len, ad, ad_len, &iv_[0], libsodium_context_.key); + last_errorno_ = + crypto_aead_chacha20poly1305_decrypt_detached(output, nullptr, input, ilen - tag_len, input + ilen - tag_len, + ad, ad_len, iv_.data(), libsodium_context_.key); if (last_errorno_ != 0) { return static_cast(error_code_t::kLibsodiumOperation); } @@ -1645,8 +1712,9 @@ ATFRAMEWORK_UTILS_API int cipher::decrypt_aead(const unsigned char *input, size_ return static_cast(error_code_t::kLibsodiumOperationTagLen); } - last_errorno_ = crypto_aead_chacha20poly1305_ietf_decrypt_detached( - output, nullptr, input, ilen - tag_len, input + ilen - tag_len, ad, ad_len, &iv_[0], libsodium_context_.key); + last_errorno_ = crypto_aead_chacha20poly1305_ietf_decrypt_detached(output, nullptr, input, ilen - tag_len, + input + ilen - tag_len, ad, ad_len, iv_.data(), + libsodium_context_.key); if (last_errorno_ != 0) { return static_cast(error_code_t::kLibsodiumOperation); } @@ -1664,8 +1732,9 @@ ATFRAMEWORK_UTILS_API int cipher::decrypt_aead(const unsigned char *input, size_ return static_cast(error_code_t::kLibsodiumOperationTagLen); } - last_errorno_ = crypto_aead_xchacha20poly1305_ietf_decrypt_detached( - output, nullptr, input, ilen - tag_len, input + ilen - tag_len, ad, ad_len, &iv_[0], libsodium_context_.key); + last_errorno_ = crypto_aead_xchacha20poly1305_ietf_decrypt_detached(output, nullptr, input, ilen - tag_len, + input + ilen - tag_len, ad, ad_len, + iv_.data(), libsodium_context_.key); if (last_errorno_ != 0) { return static_cast(error_code_t::kLibsodiumOperation); } @@ -1694,9 +1763,8 @@ ATFRAMEWORK_UTILS_API const cipher::cipher_kt_t *cipher::get_cipher_by_name(cons defined(ATFRAMEWORK_UTILS_CRYPTO_USE_BORINGSSL) if (nullptr == interface->openssl_name) { return EVP_get_cipherbyname(interface->name); - } else { - return EVP_get_cipherbyname(interface->openssl_name); } + return EVP_get_cipherbyname(interface->openssl_name); # elif defined(ATFRAMEWORK_UTILS_CRYPTO_USE_MBEDTLS) if (nullptr == interface->mbedtls_name) { return nullptr; @@ -1714,13 +1782,13 @@ ATFRAMEWORK_UTILS_API std::pair cipher::ciphertok(co } const char *b = in; - const char *e; // skip \r\n\t and space while (0 != *b && (*b == ' ' || *b == '\t' || *b == '\r' || *b == '\n' || *b == ';' || *b == ',' || *b == ':')) { ++b; } - for (e = b; 0 != *e; ++e) { + const char *e = b; + for (; 0 != *e; ++e) { if (*e == ' ' || *e == '\t' || *e == '\r' || *e == '\n' || *e == ';' || *e == ',' || *e == ':') { break; } @@ -1740,19 +1808,19 @@ ATFRAMEWORK_UTILS_API const std::vector &cipher::get_all_cipher_nam if (ret.empty()) { for (size_t i = 0; nullptr != __g_supported_ciphers[i].name; ++i) { if (__g_supported_ciphers[i].method < EN_CIMT_INNER) { - ret.push_back(__g_supported_ciphers[i].name); + ret.emplace_back(__g_supported_ciphers[i].name); continue; } if (__g_supported_ciphers[i].method == EN_CIMT_CIPHER) { if (nullptr != get_cipher_by_name(__g_supported_ciphers[i].name)) { - ret.push_back(__g_supported_ciphers[i].name); + ret.emplace_back(__g_supported_ciphers[i].name); } continue; } if (__g_supported_ciphers[i].method > EN_CIMT_LIBSODIUM) { - ret.push_back(__g_supported_ciphers[i].name); + ret.emplace_back(__g_supported_ciphers[i].name); } } } @@ -1763,7 +1831,8 @@ ATFRAMEWORK_UTILS_API const std::vector &cipher::get_all_cipher_nam ATFRAMEWORK_UTILS_API int cipher::init_global_algorithm() { # if defined(ATFRAMEWORK_UTILS_CRYPTO_USE_OPENSSL) || defined(ATFRAMEWORK_UTILS_CRYPTO_USE_LIBRESSL) || \ defined(ATFRAMEWORK_UTILS_CRYPTO_USE_BORINGSSL) - size_t counter = g_global_init_counter_++; + auto &global_init_counter = get_global_init_counter(); + size_t counter = global_init_counter++; if (0 == counter) { // No explicit initialisation or de-initialisation is necessary from openssl 1.1.0. # if (defined(OPENSSL_API_COMPAT) && OPENSSL_API_COMPAT < 0x10100000L) || \ @@ -1793,13 +1862,14 @@ ATFRAMEWORK_UTILS_API int cipher::init_global_algorithm() { ATFRAMEWORK_UTILS_API int cipher::cleanup_global_algorithm() { # if defined(ATFRAMEWORK_UTILS_CRYPTO_USE_OPENSSL) || defined(ATFRAMEWORK_UTILS_CRYPTO_USE_LIBRESSL) || \ defined(ATFRAMEWORK_UTILS_CRYPTO_USE_BORINGSSL) - size_t counter = g_global_init_counter_.load(); + auto &global_init_counter = get_global_init_counter(); + size_t counter = global_init_counter.load(); while (true) { if (0 == counter) { return 0; } - if (g_global_init_counter_.compare_exchange_strong(counter, counter - 1)) { + if (global_init_counter.compare_exchange_strong(counter, counter - 1)) { break; } } @@ -1818,3 +1888,5 @@ ATFRAMEWORK_UTILS_API int cipher::cleanup_global_algorithm() { ATFRAMEWORK_UTILS_NAMESPACE_END #endif + +// NOLINTEND(misc-include-cleaner,readability-use-concise-preprocessor-directives) diff --git a/src/algorithm/crypto_dh.cpp b/src/algorithm/crypto_dh.cpp index 8b5fa807..b62a9edc 100644 --- a/src/algorithm/crypto_dh.cpp +++ b/src/algorithm/crypto_dh.cpp @@ -1,6 +1,9 @@ // Copyright 2026 atframework // // Create by owent +// Conditional crypto backend headers and project namespace/API macros make include-cleaner and concise-preprocessor +// checks noisy in this compatibility-heavy file. +// NOLINTBEGIN(misc-include-cleaner,readability-use-concise-preprocessor-directives) #include "algorithm/crypto_dh.h" @@ -40,23 +43,14 @@ #include #include -#include +#include #include -#include - -#if defined(UTIL_CONFIG_COMPILER_CXX_STATIC_ASSERT) && UTIL_CONFIG_COMPILER_CXX_STATIC_ASSERT -# include -#endif #ifdef CRYPTO_DH_ENABLED // define max key cache length, the same as MBEDTLS_SSL_MAX_CONTENT_LEN # define CRYPTO_DH_MAX_KEY_LEN 1024 -# ifndef UNUSED -# define UNUSED(x) ((void)x) -# endif - # if defined(ATFRAMEWORK_UTILS_CRYPTO_USE_OPENSSL) || defined(ATFRAMEWORK_UTILS_CRYPTO_USE_LIBRESSL) || \ defined(ATFRAMEWORK_UTILS_CRYPTO_USE_BORINGSSL) @@ -73,7 +67,9 @@ // copy from ssl_locl.h # ifndef s2n -# define s2n(s, c) ((c[0] = (unsigned char)(((s) >> 8) & 0xff), c[1] = (unsigned char)(((s)) & 0xff)), c += 2) +# define s2n(s, c) \ + (((c)[0] = static_cast(((s) >> 8) & 0xff), (c)[1] = static_cast((s) & 0xff)), \ + (c) += 2) # endif // copy from ssl_locl.h @@ -81,8 +77,12 @@ # define NAMED_CURVE_TYPE 3 # endif +namespace { // copy from t1_lib.c of openssl 1.1.0 struct tls_curve_info { + constexpr tls_curve_info(int curve_nid, int security_bits, unsigned int curve_flags) noexcept + : nid(curve_nid), secbits(security_bits), flags(curve_flags) {} + int nid; /* Curve NID */ int secbits; /* Bits of security (from SP800-57) */ unsigned int flags; /* Flags: currently just field type */ @@ -350,22 +350,25 @@ static constexpr const tls_curve_info nid_list[] = { 224, TLS_CURVE_CUSTOM}, /* X448 (30) */ }; -# define OSSL_NELEM(x) (sizeof(x) / sizeof(x[0])) +# define OSSL_NELEM(x) (sizeof(x) / sizeof((x)[0])) static int tls1_ec_group_id2nid(int group_id, unsigned int *pflags) { - const tls_curve_info *cinfo; + const tls_curve_info *cinfo = nullptr; /* ECC curves from RFC 4492 and RFC 7027 */ - if ((group_id < 1) || ((unsigned int)group_id > OSSL_NELEM(nid_list))) return 0; + if ((group_id < 1) || (static_cast(group_id) > OSSL_NELEM(nid_list))) { + return 0; + } cinfo = nid_list + group_id - 1; - if (pflags) *pflags = cinfo->flags; + if (pflags != nullptr) { + *pflags = cinfo->flags; + } return cinfo->nid; } static int tls1_nid2group_id(int nid) { - int i; - for (i = 0; i < static_cast(OSSL_NELEM(nid_list)); i++) { + for (size_t i = 0; i < OSSL_NELEM(nid_list); ++i) { if (nid_list[i].nid == nid) { - return i + 1; + return static_cast(i + 1); } } return 0; @@ -598,6 +601,8 @@ static size_t crypto_dh_EVP_PKEY_set1_tls_encodedpoint(EVP_PKEY *pkey, const uns return static_cast(EVP_PKEY_set1_tls_encodedpoint(pkey, pt, ptlen)); # endif } + +} // namespace # elif defined(ATFRAMEWORK_UTILS_CRYPTO_USE_MBEDTLS) # include "mbedtls/ssl.h" @@ -663,6 +668,7 @@ struct dh::shared_context::random_engine_t { # endif namespace details { +namespace { static inline dh::error_code_t setup_errorno(dh &ci, int err, dh::error_code_t ret) { ci.set_last_errno(err); return ret; @@ -691,14 +697,14 @@ static constexpr const char *supported_dh_curves[][2] = { # if !defined(ATFRAMEWORK_UTILS_CRYPTO_USE_BORINGSSL) // Just like PACKET_peek_net_2() but with raw pointer static inline void openssl_peek_net_2(const unsigned char *data, unsigned int &length) { - length = ((unsigned int)(*data)) << 8; + length = static_cast(*data) << 8; length |= *(data + 1); } // Just like WPACKET_put_bytes__() but with raw pointer and without WPACKET_allocate_bytes static inline void openssl_set_net_2(unsigned char *data, unsigned int length) { - *data = (unsigned char)((length >> 8) & 0xff); - *(data + 1) = (unsigned char)(length & 0xff); + *data = static_cast((length >> 8) & 0xff); + *(data + 1) = static_cast(length & 0xff); } static inline BIGNUM *openssl_get_dh_point(const unsigned char *&input, size_t &left_size) { @@ -706,7 +712,7 @@ static inline BIGNUM *openssl_get_dh_point(const unsigned char *&input, size_t & return nullptr; } - unsigned int point_size; + unsigned int point_size = 0; openssl_peek_net_2(input, point_size); if (left_size < point_size + 2) { return nullptr; @@ -898,7 +904,7 @@ class openssl_raii { inline void reset() { ATFRAMEWORK_UTILS_NAMESPACE_ID::crypto::details::reset(data_); } - inline operator bool() const { return !!data_; } + inline operator bool() const { return data_ != nullptr; } inline const TPTR *operator->() const noexcept { return data_; } inline TPTR *operator->() noexcept { return data_; } @@ -970,6 +976,7 @@ static EVP_PKEY_CTX *initialize_pkey_ctx_by_pkey(EVP_PKEY *params_key, bool init return ret; } # endif +} // namespace } // namespace details // =============== shared context =============== @@ -1071,12 +1078,12 @@ ATFRAMEWORK_UTILS_API dh::error_code_t dh::shared_context::init(nostd::string_vi # if defined(ATFRAMEWORK_UTILS_CRYPTO_USE_OPENSSL) || defined(ATFRAMEWORK_UTILS_CRYPTO_USE_LIBRESSL) do { dh_param_->param_buffer.resize(pem_sz); - if (pem_sz > 0 && 0 == fread(&dh_param_->param_buffer[0], sizeof(unsigned char), pem_sz, pem)) { + if (pem_sz > 0 && 0 == fread(dh_param_->param_buffer.data(), sizeof(unsigned char), pem_sz, pem)) { ret = error_code_t::kReadDhparamFile; break; } details::reset(dh_param_->param); - dh_param_->param = BIO_new_mem_buf(&dh_param_->param_buffer[0], static_cast(pem_sz)); + dh_param_->param = BIO_new_mem_buf(dh_param_->param_buffer.data(), static_cast(pem_sz)); details::openssl_raii params_key{EVP_PKEY_new()}; if (nullptr == params_key.get()) { @@ -1539,7 +1546,7 @@ ATFRAMEWORK_UTILS_API dh::error_code_t dh::init(shared_context::ptr_t shared_con return ret; } - shared_context_ = shared_context_ptr; + shared_context_ = std::move(shared_context_ptr); return details::setup_errorno(*this, 0, error_code_t::kOk); } @@ -1680,7 +1687,7 @@ ATFRAMEWORK_UTILS_API dh::error_code_t dh::make_params(std::vector(group_id >> 8); - param[2] = static_cast(group_id & 0xFF); - param[3] = static_cast(encode_len); + param_data[0] = NAMED_CURVE_TYPE; + param_data[1] = static_cast(group_id >> 8); + param_data[2] = static_cast(group_id & 0xFF); + param_data[3] = static_cast(encode_len); # elif defined(ATFRAMEWORK_UTILS_CRYPTO_USE_MBEDTLS) unsigned char buf[CRYPTO_DH_MAX_KEY_LEN]; @@ -1977,7 +1985,7 @@ ATFRAMEWORK_UTILS_API dh::error_code_t dh::make_public(std::vector(BN_num_bytes(self_pubkey)); param.resize(dhparam_bnsz, 0); - BN_bn2bin(self_pubkey, ¶m[0]); + BN_bn2bin(self_pubkey, param.data()); # ifdef CRYPTO_USE_OPENSSL_WITH_OSSL_APIS details::reset(self_pubkey); # endif @@ -2015,9 +2023,10 @@ ATFRAMEWORK_UTILS_API dh::error_code_t dh::make_public(std::vector(encode_len); + param_data[0] = static_cast(encode_len); # elif defined(ATFRAMEWORK_UTILS_CRYPTO_USE_MBEDTLS) unsigned char buf[CRYPTO_DH_MAX_KEY_LEN]; @@ -2242,16 +2251,12 @@ ATFRAMEWORK_UTILS_API dh::error_code_t dh::calc_secret(std::vectoropenssl_dh_peer_key_ != EVP_PKEY_CTX_get0_peerkey(dh_context_->openssl_pkey_ctx_)) { -# endif if (EVP_PKEY_derive_set_peer(dh_context_->openssl_pkey_ctx_, dh_context_->openssl_dh_peer_key_) <= 0) { ret = details::setup_errorno(*this, static_cast(ERR_peek_error()), error_code_t::kInitDhGenerateSecret); break; } -# if !defined(ATFRAMEWORK_UTILS_CRYPTO_USE_BORINGSSL) } -# endif // puts("pkey: params"); // EVP_PKEY_print_params_fp(stdout, dh_context_->openssl_dh_pkey_, 2, nullptr); @@ -2273,18 +2278,18 @@ ATFRAMEWORK_UTILS_API dh::error_code_t dh::calc_secret(std::vector((secret_len + 7) / 8) * 8, 0); - if ((EVP_PKEY_derive(dh_context_->openssl_pkey_ctx_, &output[0], &secret_len)) <= 0) { + if ((EVP_PKEY_derive(dh_context_->openssl_pkey_ctx_, output.data(), &secret_len)) <= 0) { ret = details::setup_errorno(*this, static_cast(ERR_peek_error()), error_code_t::kInitDhGenerateSecret); break; } - output.resize(static_cast(secret_len)); + output.resize(secret_len); # elif defined(ATFRAMEWORK_UTILS_CRYPTO_USE_MBEDTLS) size_t psz = MBEDTLS_PREMASTER_SIZE; // generate next_secret output.resize(psz, 0); int res; - res = mbedtls_dhm_calc_secret(&dh_context_->mbedtls_dh_ctx_, &output[0], psz, &psz, mbedtls_ctr_drbg_random, + res = mbedtls_dhm_calc_secret(&dh_context_->mbedtls_dh_ctx_, output.data(), psz, &psz, mbedtls_ctr_drbg_random, &shared_context_->get_random_engine().ctr_drbg); if (0 != res) { ret = details::setup_errorno(*this, res, error_code_t::kInitDhGenerateSecret); @@ -2348,11 +2353,11 @@ ATFRAMEWORK_UTILS_API dh::error_code_t dh::calc_secret(std::vector((secret_len + 7) / 8) * 8, 0); - if ((EVP_PKEY_derive(dh_context_->openssl_pkey_ctx_, &output[0], &secret_len)) <= 0) { + if ((EVP_PKEY_derive(dh_context_->openssl_pkey_ctx_, output.data(), &secret_len)) <= 0) { ret = details::setup_errorno(*this, static_cast(ERR_peek_error()), error_code_t::kInitDhGenerateSecret); break; } - output.resize(static_cast(secret_len)); + output.resize(secret_len); # elif defined(ATFRAMEWORK_UTILS_CRYPTO_USE_MBEDTLS) unsigned char buf[CRYPTO_DH_MAX_KEY_LEN]; @@ -2611,5 +2616,6 @@ dh::error_code_t dh::check_or_setup_dh_pg_gy(BIGNUM *&DH_p, BIGNUM *&DH_g, BIGNU } // namespace crypto ATFRAMEWORK_UTILS_NAMESPACE_END - #endif + +// NOLINTEND(misc-include-cleaner,readability-use-concise-preprocessor-directives) diff --git a/src/algorithm/crypto_hmac.cpp b/src/algorithm/crypto_hmac.cpp index 9db0964c..976db876 100644 --- a/src/algorithm/crypto_hmac.cpp +++ b/src/algorithm/crypto_hmac.cpp @@ -2,6 +2,10 @@ // // Created by owent on 2024.12.26 +// Crypto backend headers/functions are selected through feature macros, so include-cleaner and concise-preprocessor +// checks produce noisy false positives in this compatibility-heavy file. +// NOLINTBEGIN(misc-include-cleaner,readability-use-concise-preprocessor-directives) + #include "algorithm/crypto_hmac.h" #ifdef ATFW_UTIL_MACRO_CRYPTO_HMAC_ENABLED @@ -9,6 +13,7 @@ # include # include +# include /** * @note OpenSSL version compatibility notes: @@ -108,6 +113,19 @@ namespace crypto { namespace details { +namespace { + +static inline char* get_writable_string_data(std::string& value) noexcept { + if (value.empty()) { + return nullptr; + } +# if (defined(_MSVC_LANG) && _MSVC_LANG >= 201703L) || __cplusplus >= 201703L + return value.data(); +# else + return &value[0]; // NOLINT(cppcoreguidelines-pro-bounds-constant-array-index,modernize-use-data) +# endif +} + # if defined(ATFRAMEWORK_UTILS_CRYPTO_USE_OPENSSL) || defined(ATFRAMEWORK_UTILS_CRYPTO_USE_LIBRESSL) || \ defined(ATFRAMEWORK_UTILS_CRYPTO_USE_BORINGSSL) @@ -132,7 +150,7 @@ static const EVP_MD* get_evp_md_by_type(digest_type_t type) noexcept { # if ATFW_CRYPTO_HMAC_USE_EVP_MAC -struct hmac_evp_mac_context { +struct ATFW_UTIL_SYMBOL_LOCAL hmac_evp_mac_context { EVP_MAC* mac; EVP_MAC_CTX* ctx; size_t output_length; @@ -202,7 +220,7 @@ static void free_hmac_context(void* ctx) { # else // !ATFW_CRYPTO_HMAC_USE_EVP_MAC -struct hmac_legacy_context { +struct ATFW_UTIL_SYMBOL_LOCAL hmac_legacy_context { # if ATFW_CRYPTO_HMAC_CTX_NEW HMAC_CTX* ctx; # else @@ -289,7 +307,7 @@ static const mbedtls_md_info_t* get_md_info_by_type(digest_type_t type) noexcept } } -struct hmac_mbedtls_context { +struct ATFW_UTIL_SYMBOL_LOCAL hmac_mbedtls_context { mbedtls_md_context_t ctx; bool initialized; size_t output_length; @@ -340,6 +358,7 @@ static void free_hmac_context(void* ctx) { # endif // ATFRAMEWORK_UTILS_CRYPTO_USE_MBEDTLS +} // namespace } // namespace details // ============================================================================ @@ -690,12 +709,12 @@ ATFRAMEWORK_UTILS_API std::vector hmac::compute_to_binary(digest_ size_t input_len) { size_t output_len = get_digest_output_length(type); if (output_len == 0) { - return std::vector(); + return {}; } std::vector result(output_len); if (compute(type, key, key_len, input, input_len, result.data(), &output_len) != hmac_error_code_t::kOk) { - return std::vector(); + return {}; } result.resize(output_len); return result; @@ -711,12 +730,13 @@ ATFRAMEWORK_UTILS_API std::string hmac::compute_to_hex(digest_type_t type, const const unsigned char* input, size_t input_len, bool uppercase) { std::vector binary = compute_to_binary(type, key, key_len, input, input_len); if (binary.empty()) { - return std::string(); + return {}; } std::string result; result.resize(binary.size() * 2); - ATFRAMEWORK_UTILS_NAMESPACE_ID::string::dumphex(binary.data(), binary.size(), &result[0], uppercase); + ATFRAMEWORK_UTILS_NAMESPACE_ID::string::dumphex(binary.data(), binary.size(), + details::get_writable_string_data(result), uppercase); return result; } @@ -1118,13 +1138,13 @@ ATFRAMEWORK_UTILS_API std::vector hkdf::derive_to_binary(digest_t gsl::span info, size_t okm_len) { if (okm_len == 0) { - return std::vector(); + return {}; } std::vector result(okm_len); hkdf::error_code_t ret = derive(type, salt, ikm, info, result.data(), okm_len); if (ret != error_code_t::kOk) { - return std::vector(); + return {}; } return result; } @@ -1147,3 +1167,5 @@ ATFRAMEWORK_UTILS_NAMESPACE_END # endif #endif // ATFW_UTIL_MACRO_CRYPTO_HMAC_ENABLED + +// NOLINTEND(misc-include-cleaner,readability-use-concise-preprocessor-directives) diff --git a/src/algorithm/murmur_hash.cpp b/src/algorithm/murmur_hash.cpp index 9f2cde9c..bd8b8ca6 100644 --- a/src/algorithm/murmur_hash.cpp +++ b/src/algorithm/murmur_hash.cpp @@ -1,5 +1,11 @@ // Copyright 2026 atframework +#include +#include + +#include +#include + #include #include "algorithm/murmur_hash.h" @@ -7,44 +13,98 @@ //----------------------------------------------------------------------------- // Platform-specific functions and macros -// Microsoft Visual Studio - -#if defined(_MSC_VER) - -# include - -# define ROTL32(x, y) _rotl(x, y) -# define ROTL64(x, y) _rotl64(x, y) - -# define BIG_CONSTANT(x) (x) - -// Other compilers - -#else // defined(_MSC_VER) - -inline uint32_t rotl32(uint32_t x, int8_t r) { return (x << r) | (x >> (32 - r)); } - -inline uint64_t rotl64(uint64_t x, int8_t r) { return (x << r) | (x >> (64 - r)); } - -# define ROTL32(x, y) rotl32(x, y) -# define ROTL64(x, y) rotl64(x, y) - -# define BIG_CONSTANT(x) (x##LLU) - -#endif // !defined(_MSC_VER) +namespace { +ATFW_UTIL_FORCEINLINE static uint32_t rotl32(uint32_t x, int8_t r) noexcept { return (x << r) | (x >> (32 - r)); } + +ATFW_UTIL_FORCEINLINE static uint64_t rotl64(uint64_t x, int8_t r) noexcept { return (x << r) | (x >> (64 - r)); } + +#define ROTL32(x, y) rotl32((x), (y)) +#define ROTL64(x, y) rotl64((x), (y)) +#define BIG_CONSTANT(x) UINT64_C(x) + +#if defined(_WIN32) || defined(__LITTLE_ENDIAN__) || \ + (defined(__BYTE_ORDER__) && defined(__ORDER_LITTLE_ENDIAN__) && (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)) +# define ATFW_UTIL_MURMUR_HASH_COMPILETIME_LITTLE_ENDIAN 1 +#else +# define ATFW_UTIL_MURMUR_HASH_COMPILETIME_LITTLE_ENDIAN 0 +#endif + +#if defined(__i386__) || defined(__x86_64__) || defined(__aarch64__) || defined(_M_IX86) || defined(_M_X64) || \ + defined(_M_ARM64) +# define ATFW_UTIL_MURMUR_HASH_HAS_FAST_UNALIGNED_LOAD 1 +#else +# define ATFW_UTIL_MURMUR_HASH_HAS_FAST_UNALIGNED_LOAD 0 +#endif + +#if ATFW_UTIL_MURMUR_HASH_COMPILETIME_LITTLE_ENDIAN && ATFW_UTIL_MURMUR_HASH_HAS_FAST_UNALIGNED_LOAD +# define ATFW_UTIL_MURMUR_HASH_USE_FAST_UNALIGNED_LOAD 1 +#else +# define ATFW_UTIL_MURMUR_HASH_USE_FAST_UNALIGNED_LOAD 0 +#endif + +#if ATFW_UTIL_MURMUR_HASH_USE_FAST_UNALIGNED_LOAD +# if defined(__clang__) || defined(__GNUC__) +using murmur_hash_alias_uint32_t = ATFW_EXPLICIT_MAY_ALIAS uint32_t; +using murmur_hash_alias_uint64_t = ATFW_EXPLICIT_MAY_ALIAS uint64_t; + +struct __attribute__((__packed__)) murmur_hash_unaligned_uint32_t { + murmur_hash_alias_uint32_t value; +}; + +struct __attribute__((__packed__)) murmur_hash_unaligned_uint64_t { + murmur_hash_alias_uint64_t value; +}; +# elif defined(_MSC_VER) +# pragma pack(push, 1) +struct murmur_hash_unaligned_uint32_t { + uint32_t value; +}; + +struct murmur_hash_unaligned_uint64_t { + uint64_t value; +}; +# pragma pack(pop) +# endif +#endif //----------------------------------------------------------------------------- // Block read - if your platform needs to do endian-swapping or can only // handle aligned reads, do the conversion here -ATFW_UTIL_FORCEINLINE uint32_t getblock32(const uint32_t *p, int i) { return p[i]; } +#if !ATFW_UTIL_MURMUR_HASH_USE_FAST_UNALIGNED_LOAD +ATFW_UTIL_FORCEINLINE static uint32_t getblock32_fallback(const uint8_t *p) noexcept { + return static_cast(p[0]) | (static_cast(p[1]) << 8U) | (static_cast(p[2]) << 16U) | + (static_cast(p[3]) << 24U); +} -ATFW_UTIL_FORCEINLINE uint64_t getblock64(const uint64_t *p, int i) { return p[i]; } +ATFW_UTIL_FORCEINLINE static uint64_t getblock64_fallback(const uint8_t *p) noexcept { + return static_cast(p[0]) | (static_cast(p[1]) << 8U) | (static_cast(p[2]) << 16U) | + (static_cast(p[3]) << 24U) | (static_cast(p[4]) << 32U) | + (static_cast(p[5]) << 40U) | (static_cast(p[6]) << 48U) | + (static_cast(p[7]) << 56U); +} +#endif + +ATFW_UTIL_FORCEINLINE static uint32_t getblock32(const void *p) noexcept { +#if ATFW_UTIL_MURMUR_HASH_USE_FAST_UNALIGNED_LOAD + return static_cast(p)->value; +#else + return getblock32_fallback(static_cast(p)); +#endif +} + +ATFW_UTIL_FORCEINLINE static uint64_t getblock64(const void *p) noexcept { +#if ATFW_UTIL_MURMUR_HASH_USE_FAST_UNALIGNED_LOAD + return static_cast(p)->value; +#else + return getblock64_fallback(static_cast(p)); +#endif +} //----------------------------------------------------------------------------- // Finalization mix - force all bits of a hash block to avalanche -ATFW_UTIL_FORCEINLINE uint32_t fmix32(uint32_t h) { +ATFW_UTIL_FORCEINLINE static uint32_t fmix32(uint32_t h) noexcept { h ^= h >> 16; h *= 0x85ebca6b; h ^= h >> 13; @@ -56,7 +116,7 @@ ATFW_UTIL_FORCEINLINE uint32_t fmix32(uint32_t h) { //---------- -ATFW_UTIL_FORCEINLINE uint64_t fmix64(uint64_t k) { +ATFW_UTIL_FORCEINLINE static uint64_t fmix64(uint64_t k) noexcept { k ^= k >> 33; k *= BIG_CONSTANT(0xff51afd7ed558ccd); k ^= k >> 33; @@ -65,6 +125,7 @@ ATFW_UTIL_FORCEINLINE uint64_t fmix64(uint64_t k) { return k; } +} // namespace //----------------------------------------------------------------------------- @@ -87,10 +148,10 @@ ATFRAMEWORK_UTILS_API uint32_t murmur_hash2(const void *key, int len, uint32_t s // Mix 4 bytes at a time into the hash - const unsigned char *data = (const unsigned char *)key; + const auto *data = static_cast(key); while (len >= 4) { - uint32_t k = *(uint32_t *)data; + uint32_t k = getblock32(data); k *= m; k ^= k >> r; @@ -141,11 +202,12 @@ ATFRAMEWORK_UTILS_API uint64_t murmur_hash2_64a(const void *key, int len, uint64 uint64_t h = seed ^ (static_cast(len) * m); - const uint64_t *data = (const uint64_t *)key; - const uint64_t *end = data + (len / 8); + const auto *data = static_cast(key); + const auto *end = data + (static_cast(len / 8) * 8U); while (data != end) { - uint64_t k = *data++; + uint64_t k = getblock64(data); + data += 8U; k *= m; k ^= k >> r; @@ -155,29 +217,29 @@ ATFRAMEWORK_UTILS_API uint64_t murmur_hash2_64a(const void *key, int len, uint64 h *= m; } - const unsigned char *data2 = (const unsigned char *)data; + const auto *data2 = data; switch (len & 7) { case 7: - h ^= uint64_t(data2[6]) << 48; + h ^= static_cast(data2[6]) << 48U; ATFW_EXPLICIT_FALLTHROUGH case 6: - h ^= uint64_t(data2[5]) << 40; + h ^= static_cast(data2[5]) << 40U; ATFW_EXPLICIT_FALLTHROUGH case 5: - h ^= uint64_t(data2[4]) << 32; + h ^= static_cast(data2[4]) << 32U; ATFW_EXPLICIT_FALLTHROUGH case 4: - h ^= uint64_t(data2[3]) << 24; + h ^= static_cast(data2[3]) << 24U; ATFW_EXPLICIT_FALLTHROUGH case 3: - h ^= uint64_t(data2[2]) << 16; + h ^= static_cast(data2[2]) << 16U; ATFW_EXPLICIT_FALLTHROUGH case 2: - h ^= uint64_t(data2[1]) << 8; + h ^= static_cast(data2[1]) << 8U; ATFW_EXPLICIT_FALLTHROUGH case 1: - h ^= uint64_t(data2[0]); + h ^= static_cast(data2[0]); h *= m; } @@ -194,13 +256,14 @@ ATFRAMEWORK_UTILS_API uint64_t murmur_hash2_64b(const void *key, int len, uint64 const uint32_t m = 0x5bd1e995; const int r = 24; - uint32_t h1 = uint32_t(seed) ^ static_cast(len); - uint32_t h2 = uint32_t(seed >> 32); + uint32_t h1 = static_cast(seed) ^ static_cast(len); + uint32_t h2 = static_cast(seed >> 32U); - const uint32_t *data = (const uint32_t *)key; + const auto *data = static_cast(key); while (len >= 8) { - uint32_t k1 = *data++; + uint32_t k1 = getblock32(data); + data += 4U; k1 *= m; k1 ^= k1 >> r; k1 *= m; @@ -208,7 +271,8 @@ ATFRAMEWORK_UTILS_API uint64_t murmur_hash2_64b(const void *key, int len, uint64 h1 ^= k1; len -= 4; - uint32_t k2 = *data++; + uint32_t k2 = getblock32(data); + data += 4U; k2 *= m; k2 ^= k2 >> r; k2 *= m; @@ -218,7 +282,8 @@ ATFRAMEWORK_UTILS_API uint64_t murmur_hash2_64b(const void *key, int len, uint64 } if (len >= 4) { - uint32_t k1 = *data++; + uint32_t k1 = getblock32(data); + data += 4U; k1 *= m; k1 ^= k1 >> r; k1 *= m; @@ -229,13 +294,13 @@ ATFRAMEWORK_UTILS_API uint64_t murmur_hash2_64b(const void *key, int len, uint64 switch (len) { case 3: - h2 ^= static_cast(((unsigned char *)data)[2]) << 16; + h2 ^= static_cast(data[2]) << 16U; ATFW_EXPLICIT_FALLTHROUGH case 2: - h2 ^= static_cast(((unsigned char *)data)[1]) << 8; + h2 ^= static_cast(data[1]) << 8U; ATFW_EXPLICIT_FALLTHROUGH case 1: - h2 ^= static_cast(((unsigned char *)data)[0]); + h2 ^= static_cast(data[0]); h2 *= m; } @@ -257,7 +322,7 @@ ATFRAMEWORK_UTILS_API uint64_t murmur_hash2_64b(const void *key, int len, uint64 // ===================== MurmurHash3 ===================== ATFRAMEWORK_UTILS_API uint32_t murmur_hash3_x86_32(const void *key, int len, uint32_t seed) { - const uint8_t *data = (const uint8_t *)key; + const auto *data = static_cast(key); const int nblocks = len / 4; uint32_t h1 = seed; @@ -268,11 +333,10 @@ ATFRAMEWORK_UTILS_API uint32_t murmur_hash3_x86_32(const void *key, int len, uin //---------- // body - const uint32_t *blocks = - (const uint32_t *)(data + nblocks * 4); // NOLINT(bugprone-implicit-widening-of-multiplication-result) - - for (int i = -nblocks; i; i++) { - uint32_t k1 = getblock32(blocks, i); + const uint8_t *blocks = data; + for (int i = 0; i < nblocks; ++i) { + uint32_t k1 = getblock32(blocks); + blocks += 4U; k1 *= c1; k1 = ROTL32(k1, 15); @@ -280,14 +344,13 @@ ATFRAMEWORK_UTILS_API uint32_t murmur_hash3_x86_32(const void *key, int len, uin h1 ^= k1; h1 = ROTL32(h1, 13); - h1 = h1 * 5 + 0xe6546b64; + h1 = (h1 * 5U) + 0xe6546b64U; } //---------- // tail - const uint8_t *tail = - (const uint8_t *)(data + nblocks * 4); // NOLINT(bugprone-implicit-widening-of-multiplication-result) + const auto *tail = data + (static_cast(nblocks) * 4U); uint32_t k1 = 0; @@ -319,7 +382,7 @@ ATFRAMEWORK_UTILS_API uint32_t murmur_hash3_x86_32(const void *key, int len, uin //----------------------------------------------------------------------------- ATFRAMEWORK_UTILS_API void murmur_hash3_x86_128(const void *key, const int len, uint32_t seed, uint32_t out[4]) { - const uint8_t *data = (const uint8_t *)key; + const auto *data = static_cast(key); const int nblocks = len / 16; uint32_t h1 = seed; @@ -335,14 +398,13 @@ ATFRAMEWORK_UTILS_API void murmur_hash3_x86_128(const void *key, const int len, //---------- // body - const uint32_t *blocks = - (const uint32_t *)(data + nblocks * 16); // NOLINT(bugprone-implicit-widening-of-multiplication-result) - - for (int i = -nblocks; i; i++) { - uint32_t k1 = getblock32(blocks, i * 4 + 0); - uint32_t k2 = getblock32(blocks, i * 4 + 1); - uint32_t k3 = getblock32(blocks, i * 4 + 2); - uint32_t k4 = getblock32(blocks, i * 4 + 3); + const uint8_t *blocks = data; + for (int i = 0; i < nblocks; ++i) { + uint32_t k1 = getblock32(blocks); + uint32_t k2 = getblock32(blocks + 4U); + uint32_t k3 = getblock32(blocks + 8U); + uint32_t k4 = getblock32(blocks + 12U); + blocks += 16U; k1 *= c1; k1 = ROTL32(k1, 15); @@ -351,7 +413,7 @@ ATFRAMEWORK_UTILS_API void murmur_hash3_x86_128(const void *key, const int len, h1 = ROTL32(h1, 19); h1 += h2; - h1 = h1 * 5 + 0x561ccd1b; + h1 = (h1 * 5U) + 0x561ccd1bU; k2 *= c2; k2 = ROTL32(k2, 16); @@ -360,7 +422,7 @@ ATFRAMEWORK_UTILS_API void murmur_hash3_x86_128(const void *key, const int len, h2 = ROTL32(h2, 17); h2 += h3; - h2 = h2 * 5 + 0x0bcaa747; + h2 = (h2 * 5U) + 0x0bcaa747U; k3 *= c3; k3 = ROTL32(k3, 17); @@ -369,7 +431,7 @@ ATFRAMEWORK_UTILS_API void murmur_hash3_x86_128(const void *key, const int len, h3 = ROTL32(h3, 15); h3 += h4; - h3 = h3 * 5 + 0x96cd1c35; + h3 = (h3 * 5U) + 0x96cd1c35U; k4 *= c4; k4 = ROTL32(k4, 18); @@ -378,14 +440,13 @@ ATFRAMEWORK_UTILS_API void murmur_hash3_x86_128(const void *key, const int len, h4 = ROTL32(h4, 13); h4 += h1; - h4 = h4 * 5 + 0x32ac3b17; + h4 = (h4 * 5U) + 0x32ac3b17U; } //---------- // tail - const uint8_t *tail = - (const uint8_t *)(data + nblocks * 16); // NOLINT(bugprone-implicit-widening-of-multiplication-result) + const auto *tail = data + (static_cast(nblocks) * 16U); uint32_t k1 = 0; uint32_t k2 = 0; @@ -491,7 +552,7 @@ ATFRAMEWORK_UTILS_API void murmur_hash3_x86_128(const void *key, const int len, //----------------------------------------------------------------------------- ATFRAMEWORK_UTILS_API void murmur_hash3_x64_128(const void *key, const int len, const uint32_t seed, uint64_t out[2]) { - const uint8_t *data = (const uint8_t *)key; + const auto *data = static_cast(key); const int nblocks = len / 16; uint64_t h1 = seed; @@ -503,11 +564,11 @@ ATFRAMEWORK_UTILS_API void murmur_hash3_x64_128(const void *key, const int len, //---------- // body - const uint64_t *blocks = (const uint64_t *)(data); - - for (int i = 0; i < nblocks; i++) { - uint64_t k1 = getblock64(blocks, i * 2 + 0); - uint64_t k2 = getblock64(blocks, i * 2 + 1); + const uint8_t *blocks = data; + for (int i = 0; i < nblocks; ++i) { + uint64_t k1 = getblock64(blocks); + uint64_t k2 = getblock64(blocks + 8U); + blocks += 16U; k1 *= c1; k1 = ROTL64(k1, 31); @@ -516,7 +577,7 @@ ATFRAMEWORK_UTILS_API void murmur_hash3_x64_128(const void *key, const int len, h1 = ROTL64(h1, 27); h1 += h2; - h1 = h1 * 5 + 0x52dce729; + h1 = (h1 * UINT64_C(5)) + UINT64_C(0x52dce729); k2 *= c2; k2 = ROTL64(k2, 33); @@ -525,67 +586,66 @@ ATFRAMEWORK_UTILS_API void murmur_hash3_x64_128(const void *key, const int len, h2 = ROTL64(h2, 31); h2 += h1; - h2 = h2 * 5 + 0x38495ab5; + h2 = (h2 * UINT64_C(5)) + UINT64_C(0x38495ab5); } //---------- // tail - const uint8_t *tail = - (const uint8_t *)(data + nblocks * 16); // NOLINT(bugprone-implicit-widening-of-multiplication-result) + const auto *tail = data + (static_cast(nblocks) * 16U); uint64_t k1 = 0; uint64_t k2 = 0; switch (len & 15) { case 15: - k2 ^= ((uint64_t)tail[14]) << 48; + k2 ^= static_cast(tail[14]) << 48U; ATFW_EXPLICIT_FALLTHROUGH case 14: - k2 ^= ((uint64_t)tail[13]) << 40; + k2 ^= static_cast(tail[13]) << 40U; ATFW_EXPLICIT_FALLTHROUGH case 13: - k2 ^= ((uint64_t)tail[12]) << 32; + k2 ^= static_cast(tail[12]) << 32U; ATFW_EXPLICIT_FALLTHROUGH case 12: - k2 ^= ((uint64_t)tail[11]) << 24; + k2 ^= static_cast(tail[11]) << 24U; ATFW_EXPLICIT_FALLTHROUGH case 11: - k2 ^= ((uint64_t)tail[10]) << 16; + k2 ^= static_cast(tail[10]) << 16U; ATFW_EXPLICIT_FALLTHROUGH case 10: - k2 ^= ((uint64_t)tail[9]) << 8; + k2 ^= static_cast(tail[9]) << 8U; ATFW_EXPLICIT_FALLTHROUGH case 9: - k2 ^= ((uint64_t)tail[8]) << 0; + k2 ^= static_cast(tail[8]); k2 *= c2; k2 = ROTL64(k2, 33); k2 *= c1; h2 ^= k2; ATFW_EXPLICIT_FALLTHROUGH case 8: - k1 ^= ((uint64_t)tail[7]) << 56; + k1 ^= static_cast(tail[7]) << 56U; ATFW_EXPLICIT_FALLTHROUGH case 7: - k1 ^= ((uint64_t)tail[6]) << 48; + k1 ^= static_cast(tail[6]) << 48U; ATFW_EXPLICIT_FALLTHROUGH case 6: - k1 ^= ((uint64_t)tail[5]) << 40; + k1 ^= static_cast(tail[5]) << 40U; ATFW_EXPLICIT_FALLTHROUGH case 5: - k1 ^= ((uint64_t)tail[4]) << 32; + k1 ^= static_cast(tail[4]) << 32U; ATFW_EXPLICIT_FALLTHROUGH case 4: - k1 ^= ((uint64_t)tail[3]) << 24; + k1 ^= static_cast(tail[3]) << 24U; ATFW_EXPLICIT_FALLTHROUGH case 3: - k1 ^= ((uint64_t)tail[2]) << 16; + k1 ^= static_cast(tail[2]) << 16U; ATFW_EXPLICIT_FALLTHROUGH case 2: - k1 ^= ((uint64_t)tail[1]) << 8; + k1 ^= static_cast(tail[1]) << 8U; ATFW_EXPLICIT_FALLTHROUGH case 1: - k1 ^= ((uint64_t)tail[0]) << 0; + k1 ^= static_cast(tail[0]); k1 *= c1; k1 = ROTL64(k1, 31); k1 *= c2; @@ -614,4 +674,3 @@ ATFRAMEWORK_UTILS_API void murmur_hash3_x64_128(const void *key, const int len, //----------------------------------------------------------------------------- } // namespace hash ATFRAMEWORK_UTILS_NAMESPACE_END - diff --git a/src/algorithm/sha.cpp b/src/algorithm/sha.cpp index 21abe834..fd327fe8 100644 --- a/src/algorithm/sha.cpp +++ b/src/algorithm/sha.cpp @@ -1,8 +1,16 @@ // Copyright 2026 atframework +// Crypto backend headers/functions are selected through feature macros, so include-cleaner reports noisy false +// positives for this compatibility file. +// NOLINTBEGIN(misc-include-cleaner) + #include +#include +#include +#include #include +#include #include @@ -16,34 +24,47 @@ ATFRAMEWORK_UTILS_NAMESPACE_BEGIN namespace hash { -namespace detail { +namespace { +static inline char *get_writable_string_data(std::string &value) noexcept { + if (value.empty()) { + return nullptr; + } +#if (defined(_MSVC_LANG) && _MSVC_LANG >= 201703L) || __cplusplus >= 201703L + return value.data(); +#else + return &value[0]; // NOLINT(cppcoreguidelines-pro-bounds-constant-array-index,modernize-use-data) +#endif +} + #if defined(UTIL_HASH_IMPLEMENT_SHA_USING_OPENSSL) && UTIL_HASH_IMPLEMENT_SHA_USING_OPENSSL -struct sha_inner_data { +struct ATFW_UTIL_SYMBOL_LOCAL sha_internal_data { unsigned char output[EVP_MAX_MD_SIZE]; EVP_MD_CTX *ctx; }; -static inline sha_inner_data *into_inner_type(void *in) { return reinterpret_cast(in); } +static inline sha_internal_data *into_internal_type(void *in) { return reinterpret_cast(in); } -static inline void free_inner_type(void *in, ATFRAMEWORK_UTILS_NAMESPACE_ID::hash::sha::type) { +static inline void free_internal_type(void *in, ATFRAMEWORK_UTILS_NAMESPACE_ID::hash::sha::type) { if (in == nullptr) { return; } - if (into_inner_type(in)->ctx != nullptr) { + if (into_internal_type(in)->ctx != nullptr) { # if OPENSSL_VERSION_NUMBER < 0x10100000L - EVP_MD_CTX_destroy(into_inner_type(in)->ctx); + EVP_MD_CTX_destroy(into_internal_type(in)->ctx); # else - EVP_MD_CTX_free(into_inner_type(in)->ctx); + EVP_MD_CTX_free(into_internal_type(in)->ctx); # endif - into_inner_type(in)->ctx = nullptr; + into_internal_type(in)->ctx = nullptr; } - free(into_inner_type(in)); + // NOLINTNEXTLINE(cppcoreguidelines-no-malloc) + free(into_internal_type(in)); } -static inline sha_inner_data *malloc_inner_type(ATFRAMEWORK_UTILS_NAMESPACE_ID::hash::sha::type t) { - sha_inner_data *ret = reinterpret_cast(malloc(sizeof(sha_inner_data))); +static inline sha_internal_data *malloc_internal_type(ATFRAMEWORK_UTILS_NAMESPACE_ID::hash::sha::type t) { + // NOLINTNEXTLINE(cppcoreguidelines-no-malloc) + sha_internal_data *ret = reinterpret_cast(malloc(sizeof(sha_internal_data))); if (ret == nullptr) { return nullptr; } @@ -53,7 +74,7 @@ static inline sha_inner_data *malloc_inner_type(ATFRAMEWORK_UTILS_NAMESPACE_ID:: ret->ctx = EVP_MD_CTX_new(); # endif if (ret->ctx == nullptr) { - free_inner_type(ret, t); + free_internal_type(ret, t); return nullptr; } @@ -79,12 +100,12 @@ static inline sha_inner_data *malloc_inner_type(ATFRAMEWORK_UTILS_NAMESPACE_ID:: } if (md == nullptr) { - free_inner_type(ret, t); + free_internal_type(ret, t); return nullptr; } if (1 != EVP_DigestInit_ex(ret->ctx, md, nullptr)) { - free_inner_type(ret, t); + free_internal_type(ret, t); return nullptr; } @@ -96,11 +117,11 @@ static inline unsigned char *get_output_buffer(void *in) { return nullptr; } - return into_inner_type(in)->output; + return into_internal_type(in)->output; } #elif defined(UTIL_HASH_IMPLEMENT_SHA_USING_MBEDTLS) && UTIL_HASH_IMPLEMENT_SHA_USING_MBEDTLS -struct sha_inner_data { +struct ATFW_UTIL_SYMBOL_LOCAL sha_internal_data { unsigned char output[64]; union { mbedtls_sha1_context sha1_context; @@ -111,14 +132,14 @@ struct sha_inner_data { }; }; -static inline sha_inner_data *into_inner_type(void *in) { return reinterpret_cast(in); } +static inline sha_internal_data *into_internal_type(void *in) { return reinterpret_cast(in); } -static inline void free_inner_type(void *in, ATFRAMEWORK_UTILS_NAMESPACE_ID::hash::sha::type t) { +static inline void free_internal_type(void *in, ATFRAMEWORK_UTILS_NAMESPACE_ID::hash::sha::type t) { if (in == nullptr) { return; } - sha_inner_data *obj = into_inner_type(in); + sha_internal_data *obj = into_internal_type(in); switch (t) { case ATFRAMEWORK_UTILS_NAMESPACE_ID::hash::sha::EN_ALGORITHM_SHA1: @@ -134,17 +155,17 @@ static inline void free_inner_type(void *in, ATFRAMEWORK_UTILS_NAMESPACE_ID::has mbedtls_sha512_free(&obj->sha384_context); break; case ATFRAMEWORK_UTILS_NAMESPACE_ID::hash::sha::EN_ALGORITHM_SHA512: - mbedtls_sha512_free(&obj->sha384_context); + mbedtls_sha512_free(&obj->sha512_context); break; default: break; } - free(into_inner_type(in)); + free(into_internal_type(in)); } -static inline sha_inner_data *malloc_inner_type(ATFRAMEWORK_UTILS_NAMESPACE_ID::hash::sha::type t) { - sha_inner_data *ret = reinterpret_cast(malloc(sizeof(sha_inner_data))); +static inline sha_internal_data *malloc_internal_type(ATFRAMEWORK_UTILS_NAMESPACE_ID::hash::sha::type t) { + sha_internal_data *ret = reinterpret_cast(malloc(sizeof(sha_internal_data))); if (ret == nullptr) { return nullptr; } @@ -186,9 +207,9 @@ static inline sha_inner_data *malloc_inner_type(ATFRAMEWORK_UTILS_NAMESPACE_ID:: case ATFRAMEWORK_UTILS_NAMESPACE_ID::hash::sha::EN_ALGORITHM_SHA512: mbedtls_sha512_init(&ret->sha512_context); # if MBEDTLS_VERSION_MAJOR >= 3 - is_success = 0 == mbedtls_sha512_starts(&ret->sha384_context, 0); + is_success = 0 == mbedtls_sha512_starts(&ret->sha512_context, 0); # else - is_success = 0 == mbedtls_sha512_starts_ret(&ret->sha384_context, 0); + is_success = 0 == mbedtls_sha512_starts_ret(&ret->sha512_context, 0); # endif break; default: @@ -196,7 +217,7 @@ static inline sha_inner_data *malloc_inner_type(ATFRAMEWORK_UTILS_NAMESPACE_ID:: } if (false == is_success) { - free_inner_type(ret, t); + free_internal_type(ret, t); ret = nullptr; } @@ -208,7 +229,7 @@ static inline unsigned char *get_output_buffer(void *in) { return nullptr; } - return into_inner_type(in)->output; + return into_internal_type(in)->output; } #else # ifndef UL64 @@ -287,7 +308,7 @@ struct sha512_context_t { 0: Use SHA-512, or 1: Use SHA-384. */ }; -struct sha_inner_data { +struct sha_internal_data { unsigned char output[64]; union { sha1_context_t sha1_context; @@ -298,20 +319,20 @@ struct sha_inner_data { }; }; -static inline sha_inner_data *into_inner_type(void *in) { return reinterpret_cast(in); } +static inline sha_internal_data *into_internal_type(void *in) { return reinterpret_cast(in); } -static inline void free_inner_type(void *in, ATFRAMEWORK_UTILS_NAMESPACE_ID::hash::sha::type) { +static inline void free_internal_type(void *in, ATFRAMEWORK_UTILS_NAMESPACE_ID::hash::sha::type) { if (in == nullptr) { return; } - free(into_inner_type(in)); + free(into_internal_type(in)); } /* * SHA-1 context setup */ -static void inner_sha1_start(sha1_context_t &ctx) { +static void internal_sha1_start(sha1_context_t &ctx) { ctx.total[0] = 0; ctx.total[1] = 0; @@ -322,7 +343,7 @@ static void inner_sha1_start(sha1_context_t &ctx) { ctx.state[4] = 0xC3D2E1F0; } -static void inner_sha256_start(sha256_context_t &ctx, bool is224) { +static void internal_sha256_start(sha256_context_t &ctx, bool is224) { ctx.total[0] = 0; ctx.total[1] = 0; @@ -354,7 +375,7 @@ static void inner_sha256_start(sha256_context_t &ctx, bool is224) { /* * SHA-512 context setup */ -static void inner_sha512_starts_ret(sha512_context_t &ctx, bool is384) { +static void internal_sha512_starts_ret(sha512_context_t &ctx, bool is384) { ctx.total[0] = 0; ctx.total[1] = 0; @@ -383,8 +404,8 @@ static void inner_sha512_starts_ret(sha512_context_t &ctx, bool is384) { } } -static sha_inner_data *malloc_inner_type(ATFRAMEWORK_UTILS_NAMESPACE_ID::hash::sha::type t) { - sha_inner_data *ret = reinterpret_cast(malloc(sizeof(sha_inner_data))); +static sha_internal_data *malloc_internal_type(ATFRAMEWORK_UTILS_NAMESPACE_ID::hash::sha::type t) { + sha_internal_data *ret = reinterpret_cast(malloc(sizeof(sha_internal_data))); if (ret == nullptr) { return nullptr; } @@ -392,23 +413,23 @@ static sha_inner_data *malloc_inner_type(ATFRAMEWORK_UTILS_NAMESPACE_ID::hash::s switch (t) { case ATFRAMEWORK_UTILS_NAMESPACE_ID::hash::sha::EN_ALGORITHM_SHA1: memset(&ret->sha1_context, 0, sizeof(ret->sha1_context)); - inner_sha1_start(ret->sha1_context); + internal_sha1_start(ret->sha1_context); break; case ATFRAMEWORK_UTILS_NAMESPACE_ID::hash::sha::EN_ALGORITHM_SHA224: memset(&ret->sha224_context, 0, sizeof(ret->sha224_context)); - inner_sha256_start(ret->sha224_context, true); + internal_sha256_start(ret->sha224_context, true); break; case ATFRAMEWORK_UTILS_NAMESPACE_ID::hash::sha::EN_ALGORITHM_SHA256: memset(&ret->sha256_context, 0, sizeof(ret->sha256_context)); - inner_sha256_start(ret->sha256_context, false); + internal_sha256_start(ret->sha256_context, false); break; case ATFRAMEWORK_UTILS_NAMESPACE_ID::hash::sha::EN_ALGORITHM_SHA384: memset(&ret->sha384_context, 0, sizeof(ret->sha384_context)); - inner_sha512_starts_ret(ret->sha384_context, true); + internal_sha512_starts_ret(ret->sha384_context, true); break; case ATFRAMEWORK_UTILS_NAMESPACE_ID::hash::sha::EN_ALGORITHM_SHA512: memset(&ret->sha512_context, 0, sizeof(ret->sha512_context)); - inner_sha512_starts_ret(ret->sha384_context, false); + internal_sha512_starts_ret(ret->sha512_context, false); break; default: break; @@ -422,10 +443,10 @@ static inline unsigned char *get_output_buffer(void *in) { return nullptr; } - return into_inner_type(in)->output; + return into_internal_type(in)->output; } -static void inner_internal_sha1_process(sha1_context_t &ctx, const unsigned char data[64]) { +static void internal_sha1_process(sha1_context_t &ctx, const unsigned char data[64]) { uint32_t temp, W[16], A, B, C, D, E; GET_UINT32_BE(W[0], data, 0); @@ -585,7 +606,7 @@ static void inner_internal_sha1_process(sha1_context_t &ctx, const unsigned char /* * SHA-1 process buffer */ -static void inner_sha1_update(sha1_context_t &ctx, const unsigned char *input, size_t ilen) { +static void internal_sha1_update(sha1_context_t &ctx, const unsigned char *input, size_t ilen) { size_t fill; uint32_t left; @@ -604,7 +625,7 @@ static void inner_sha1_update(sha1_context_t &ctx, const unsigned char *input, s if (left && ilen >= fill) { memcpy((void *)(ctx.buffer + left), input, fill); - inner_internal_sha1_process(ctx, ctx.buffer); + internal_sha1_process(ctx, ctx.buffer); input += fill; ilen -= fill; @@ -612,7 +633,7 @@ static void inner_sha1_update(sha1_context_t &ctx, const unsigned char *input, s } while (ilen >= 64) { - inner_internal_sha1_process(ctx, input); + internal_sha1_process(ctx, input); input += 64; ilen -= 64; @@ -626,7 +647,7 @@ static void inner_sha1_update(sha1_context_t &ctx, const unsigned char *input, s /* * SHA-1 final digest */ -static void inner_sha1_finish(sha1_context_t &ctx, unsigned char output[20]) { +static void internal_sha1_finish(sha1_context_t &ctx, unsigned char output[20]) { uint32_t used; uint32_t high, low; @@ -644,7 +665,7 @@ static void inner_sha1_finish(sha1_context_t &ctx, unsigned char output[20]) { /* We'll need an extra block */ memset(ctx.buffer + used, 0, 64 - used); - inner_internal_sha1_process(ctx, ctx.buffer); + internal_sha1_process(ctx, ctx.buffer); memset(ctx.buffer, 0, 56); } @@ -658,7 +679,7 @@ static void inner_sha1_finish(sha1_context_t &ctx, unsigned char output[20]) { PUT_UINT32_BE(high, ctx.buffer, 56); PUT_UINT32_BE(low, ctx.buffer, 60); - inner_internal_sha1_process(ctx, ctx.buffer); + internal_sha1_process(ctx, ctx.buffer); /* * Output final state @@ -670,7 +691,7 @@ static void inner_sha1_finish(sha1_context_t &ctx, unsigned char output[20]) { PUT_UINT32_BE(ctx.state[4], output, 16); } -static void inner_internal_sha256_process(sha256_context_t &ctx, const unsigned char data[64]) { +static void internal_sha256_process(sha256_context_t &ctx, const unsigned char data[64]) { uint32_t temp1, temp2, W[64]; uint32_t A[8]; unsigned int i; @@ -752,7 +773,7 @@ static void inner_internal_sha256_process(sha256_context_t &ctx, const unsigned /* * SHA-256 process buffer */ -static void inner_sha256_update(sha256_context_t &ctx, const unsigned char *input, size_t ilen) { +static void internal_sha256_update(sha256_context_t &ctx, const unsigned char *input, size_t ilen) { size_t fill; uint32_t left; @@ -769,7 +790,7 @@ static void inner_sha256_update(sha256_context_t &ctx, const unsigned char *inpu if (left && ilen >= fill) { memcpy((void *)(ctx.buffer + left), input, fill); - inner_internal_sha256_process(ctx, ctx.buffer); + internal_sha256_process(ctx, ctx.buffer); input += fill; ilen -= fill; @@ -777,7 +798,7 @@ static void inner_sha256_update(sha256_context_t &ctx, const unsigned char *inpu } while (ilen >= 64) { - inner_internal_sha256_process(ctx, input); + internal_sha256_process(ctx, input); input += 64; ilen -= 64; @@ -789,7 +810,7 @@ static void inner_sha256_update(sha256_context_t &ctx, const unsigned char *inpu /* * SHA-256 final digest */ -static void inner_sha256_finish(sha256_context_t &ctx, unsigned char output[32]) { +static void internal_sha256_finish(sha256_context_t &ctx, unsigned char output[32]) { uint32_t used; uint32_t high, low; @@ -807,7 +828,7 @@ static void inner_sha256_finish(sha256_context_t &ctx, unsigned char output[32]) /* We'll need an extra block */ memset(ctx.buffer + used, 0, 64 - used); - inner_internal_sha256_process(ctx, ctx.buffer); + internal_sha256_process(ctx, ctx.buffer); memset(ctx.buffer, 0, 56); } @@ -821,7 +842,7 @@ static void inner_sha256_finish(sha256_context_t &ctx, unsigned char output[32]) PUT_UINT32_BE(high, ctx.buffer, 56); PUT_UINT32_BE(low, ctx.buffer, 60); - inner_internal_sha256_process(ctx, ctx.buffer); + internal_sha256_process(ctx, ctx.buffer); /* * Output final state @@ -837,7 +858,7 @@ static void inner_sha256_finish(sha256_context_t &ctx, unsigned char output[32]) if (ctx.is224 == 0) PUT_UINT32_BE(ctx.state[7], output, 28); } -static void inner_internal_sha512_process(sha512_context_t &ctx, const unsigned char data[128]) { +static void internal_sha512_process(sha512_context_t &ctx, const unsigned char data[128]) { int i; uint64_t temp1, temp2, W[80]; uint64_t A, B, C, D, E, F, G, H; @@ -946,7 +967,7 @@ static void inner_internal_sha512_process(sha512_context_t &ctx, const unsigned /* * SHA-512 process buffer */ -static void inner_sha512_update(sha512_context_t &ctx, const unsigned char *input, size_t ilen) { +static void internal_sha512_update(sha512_context_t &ctx, const unsigned char *input, size_t ilen) { size_t fill; unsigned int left; @@ -964,7 +985,7 @@ static void inner_sha512_update(sha512_context_t &ctx, const unsigned char *inpu if (left && ilen >= fill) { memcpy((void *)(ctx.buffer + left), input, fill); - inner_internal_sha512_process(ctx, ctx.buffer); + internal_sha512_process(ctx, ctx.buffer); input += fill; ilen -= fill; @@ -972,7 +993,7 @@ static void inner_sha512_update(sha512_context_t &ctx, const unsigned char *inpu } while (ilen >= 128) { - inner_internal_sha512_process(ctx, input); + internal_sha512_process(ctx, input); input += 128; ilen -= 128; @@ -986,7 +1007,7 @@ static void inner_sha512_update(sha512_context_t &ctx, const unsigned char *inpu /* * SHA-512 final digest */ -static void inner_sha512_finish(sha512_context_t &ctx, unsigned char output[64]) { +static void internal_sha512_finish(sha512_context_t &ctx, unsigned char output[64]) { unsigned used; uint64_t high, low; @@ -1004,7 +1025,7 @@ static void inner_sha512_finish(sha512_context_t &ctx, unsigned char output[64]) /* We'll need an extra block */ memset(ctx.buffer + used, 0, 128 - used); - inner_internal_sha512_process(ctx, ctx.buffer); + internal_sha512_process(ctx, ctx.buffer); memset(ctx.buffer, 0, 112); } @@ -1018,7 +1039,7 @@ static void inner_sha512_finish(sha512_context_t &ctx, unsigned char output[64]) PUT_UINT64_BE(high, ctx.buffer, 112); PUT_UINT64_BE(low, ctx.buffer, 120); - inner_internal_sha512_process(ctx, ctx.buffer); + internal_sha512_process(ctx, ctx.buffer); /* * Output final state @@ -1036,23 +1057,23 @@ static void inner_sha512_finish(sha512_context_t &ctx, unsigned char output[64]) } } #endif -} // namespace detail +} // namespace ATFRAMEWORK_UTILS_API sha::sha() : hash_type_(EN_ALGORITHM_UNINITED), private_raw_data_(nullptr) {} ATFRAMEWORK_UTILS_API sha::~sha() { close(); } -ATFRAMEWORK_UTILS_API sha::sha(sha &&other) : hash_type_(EN_ALGORITHM_UNINITED), private_raw_data_(nullptr) { +ATFRAMEWORK_UTILS_API sha::sha(sha &&other) noexcept : hash_type_(EN_ALGORITHM_UNINITED), private_raw_data_(nullptr) { swap(other); } -ATFRAMEWORK_UTILS_API sha &sha::operator=(sha &&other) { +ATFRAMEWORK_UTILS_API sha &sha::operator=(sha &&other) noexcept { swap(other); return *this; } ATFRAMEWORK_UTILS_API bool sha::init(type t) { close(); - private_raw_data_ = detail::malloc_inner_type(t); + private_raw_data_ = malloc_internal_type(t); if (private_raw_data_ == nullptr) { return false; } @@ -1066,57 +1087,56 @@ ATFRAMEWORK_UTILS_API void sha::close() { return; } - detail::free_inner_type(private_raw_data_, hash_type_); + free_internal_type(private_raw_data_, hash_type_); hash_type_ = EN_ALGORITHM_UNINITED; private_raw_data_ = nullptr; - return; } -ATFRAMEWORK_UTILS_API void sha::swap(sha &other) { +ATFRAMEWORK_UTILS_API void sha::swap(sha &other) noexcept { using std::swap; swap(hash_type_, other.hash_type_); swap(private_raw_data_, other.private_raw_data_); } ATFRAMEWORK_UTILS_API bool sha::update(const unsigned char *in, size_t inlen) { - detail::sha_inner_data *inner_obj = detail::into_inner_type(private_raw_data_); - if (inner_obj == nullptr) { + sha_internal_data *internal_obj = into_internal_type(private_raw_data_); + if (internal_obj == nullptr) { return false; } #if defined(UTIL_HASH_IMPLEMENT_SHA_USING_OPENSSL) && UTIL_HASH_IMPLEMENT_SHA_USING_OPENSSL - return 1 == EVP_DigestUpdate(inner_obj->ctx, reinterpret_cast(in), inlen); + return 1 == EVP_DigestUpdate(internal_obj->ctx, reinterpret_cast(in), inlen); #elif defined(UTIL_HASH_IMPLEMENT_SHA_USING_MBEDTLS) && UTIL_HASH_IMPLEMENT_SHA_USING_MBEDTLS switch (hash_type_) { case ATFRAMEWORK_UTILS_NAMESPACE_ID::hash::sha::EN_ALGORITHM_SHA1: # if MBEDTLS_VERSION_MAJOR >= 3 - return 0 == mbedtls_sha1_update(&inner_obj->sha1_context, in, inlen); + return 0 == mbedtls_sha1_update(&internal_obj->sha1_context, in, inlen); # else - return 0 == mbedtls_sha1_update_ret(&inner_obj->sha1_context, in, inlen); + return 0 == mbedtls_sha1_update_ret(&internal_obj->sha1_context, in, inlen); # endif case ATFRAMEWORK_UTILS_NAMESPACE_ID::hash::sha::EN_ALGORITHM_SHA224: # if MBEDTLS_VERSION_MAJOR >= 3 - return 0 == mbedtls_sha256_update(&inner_obj->sha224_context, in, inlen); + return 0 == mbedtls_sha256_update(&internal_obj->sha224_context, in, inlen); # else - return 0 == mbedtls_sha256_update_ret(&inner_obj->sha224_context, in, inlen); + return 0 == mbedtls_sha256_update_ret(&internal_obj->sha224_context, in, inlen); # endif case ATFRAMEWORK_UTILS_NAMESPACE_ID::hash::sha::EN_ALGORITHM_SHA256: # if MBEDTLS_VERSION_MAJOR >= 3 - return 0 == mbedtls_sha256_update(&inner_obj->sha256_context, in, inlen); + return 0 == mbedtls_sha256_update(&internal_obj->sha256_context, in, inlen); # else - return 0 == mbedtls_sha256_update_ret(&inner_obj->sha256_context, in, inlen); + return 0 == mbedtls_sha256_update_ret(&internal_obj->sha256_context, in, inlen); # endif case ATFRAMEWORK_UTILS_NAMESPACE_ID::hash::sha::EN_ALGORITHM_SHA384: # if MBEDTLS_VERSION_MAJOR >= 3 - return 0 == mbedtls_sha512_update(&inner_obj->sha384_context, in, inlen); + return 0 == mbedtls_sha512_update(&internal_obj->sha384_context, in, inlen); # else - return 0 == mbedtls_sha512_update_ret(&inner_obj->sha384_context, in, inlen); + return 0 == mbedtls_sha512_update_ret(&internal_obj->sha384_context, in, inlen); # endif case ATFRAMEWORK_UTILS_NAMESPACE_ID::hash::sha::EN_ALGORITHM_SHA512: # if MBEDTLS_VERSION_MAJOR >= 3 - return 0 == mbedtls_sha512_update(&inner_obj->sha512_context, in, inlen); + return 0 == mbedtls_sha512_update(&internal_obj->sha512_context, in, inlen); # else - return 0 == mbedtls_sha512_update_ret(&inner_obj->sha512_context, in, inlen); + return 0 == mbedtls_sha512_update_ret(&internal_obj->sha512_context, in, inlen); # endif default: break; @@ -1125,19 +1145,19 @@ ATFRAMEWORK_UTILS_API bool sha::update(const unsigned char *in, size_t inlen) { #else switch (hash_type_) { case ATFRAMEWORK_UTILS_NAMESPACE_ID::hash::sha::EN_ALGORITHM_SHA1: - detail::inner_sha1_update(inner_obj->sha1_context, in, inlen); + internal_sha1_update(internal_obj->sha1_context, in, inlen); return true; case ATFRAMEWORK_UTILS_NAMESPACE_ID::hash::sha::EN_ALGORITHM_SHA224: - detail::inner_sha256_update(inner_obj->sha224_context, in, inlen); + internal_sha256_update(internal_obj->sha224_context, in, inlen); return true; case ATFRAMEWORK_UTILS_NAMESPACE_ID::hash::sha::EN_ALGORITHM_SHA256: - detail::inner_sha256_update(inner_obj->sha256_context, in, inlen); + internal_sha256_update(internal_obj->sha256_context, in, inlen); return true; case ATFRAMEWORK_UTILS_NAMESPACE_ID::hash::sha::EN_ALGORITHM_SHA384: - detail::inner_sha512_update(inner_obj->sha384_context, in, inlen); + internal_sha512_update(internal_obj->sha384_context, in, inlen); return true; case ATFRAMEWORK_UTILS_NAMESPACE_ID::hash::sha::EN_ALGORITHM_SHA512: - detail::inner_sha512_update(inner_obj->sha512_context, in, inlen); + internal_sha512_update(internal_obj->sha512_context, in, inlen); return true; default: break; @@ -1147,44 +1167,44 @@ ATFRAMEWORK_UTILS_API bool sha::update(const unsigned char *in, size_t inlen) { } ATFRAMEWORK_UTILS_API bool sha::final() { - detail::sha_inner_data *inner_obj = detail::into_inner_type(private_raw_data_); - if (inner_obj == nullptr) { + sha_internal_data *internal_obj = into_internal_type(private_raw_data_); + if (internal_obj == nullptr) { return false; } #if defined(UTIL_HASH_IMPLEMENT_SHA_USING_OPENSSL) && UTIL_HASH_IMPLEMENT_SHA_USING_OPENSSL unsigned int md_len = 0; - return 1 == EVP_DigestFinal_ex(inner_obj->ctx, inner_obj->output, &md_len); + return 1 == EVP_DigestFinal_ex(internal_obj->ctx, internal_obj->output, &md_len); #elif defined(UTIL_HASH_IMPLEMENT_SHA_USING_MBEDTLS) && UTIL_HASH_IMPLEMENT_SHA_USING_MBEDTLS switch (hash_type_) { case ATFRAMEWORK_UTILS_NAMESPACE_ID::hash::sha::EN_ALGORITHM_SHA1: # if MBEDTLS_VERSION_MAJOR >= 3 - return 0 == mbedtls_sha1_finish(&inner_obj->sha1_context, inner_obj->output); + return 0 == mbedtls_sha1_finish(&internal_obj->sha1_context, internal_obj->output); # else - return 0 == mbedtls_sha1_finish_ret(&inner_obj->sha1_context, inner_obj->output); + return 0 == mbedtls_sha1_finish_ret(&internal_obj->sha1_context, internal_obj->output); # endif case ATFRAMEWORK_UTILS_NAMESPACE_ID::hash::sha::EN_ALGORITHM_SHA224: # if MBEDTLS_VERSION_MAJOR >= 3 - return 0 == mbedtls_sha256_finish(&inner_obj->sha224_context, inner_obj->output); + return 0 == mbedtls_sha256_finish(&internal_obj->sha224_context, internal_obj->output); # else - return 0 == mbedtls_sha256_finish_ret(&inner_obj->sha224_context, inner_obj->output); + return 0 == mbedtls_sha256_finish_ret(&internal_obj->sha224_context, internal_obj->output); # endif case ATFRAMEWORK_UTILS_NAMESPACE_ID::hash::sha::EN_ALGORITHM_SHA256: # if MBEDTLS_VERSION_MAJOR >= 3 - return 0 == mbedtls_sha256_finish(&inner_obj->sha256_context, inner_obj->output); + return 0 == mbedtls_sha256_finish(&internal_obj->sha256_context, internal_obj->output); # else - return 0 == mbedtls_sha256_finish_ret(&inner_obj->sha256_context, inner_obj->output); + return 0 == mbedtls_sha256_finish_ret(&internal_obj->sha256_context, internal_obj->output); # endif case ATFRAMEWORK_UTILS_NAMESPACE_ID::hash::sha::EN_ALGORITHM_SHA384: # if MBEDTLS_VERSION_MAJOR >= 3 - return 0 == mbedtls_sha512_finish(&inner_obj->sha384_context, inner_obj->output); + return 0 == mbedtls_sha512_finish(&internal_obj->sha384_context, internal_obj->output); # else - return 0 == mbedtls_sha512_finish_ret(&inner_obj->sha384_context, inner_obj->output); + return 0 == mbedtls_sha512_finish_ret(&internal_obj->sha384_context, internal_obj->output); # endif case ATFRAMEWORK_UTILS_NAMESPACE_ID::hash::sha::EN_ALGORITHM_SHA512: # if MBEDTLS_VERSION_MAJOR >= 3 - return 0 == mbedtls_sha512_finish(&inner_obj->sha512_context, inner_obj->output); + return 0 == mbedtls_sha512_finish(&internal_obj->sha512_context, internal_obj->output); # else - return 0 == mbedtls_sha512_finish_ret(&inner_obj->sha512_context, inner_obj->output); + return 0 == mbedtls_sha512_finish_ret(&internal_obj->sha512_context, internal_obj->output); # endif default: break; @@ -1193,19 +1213,19 @@ ATFRAMEWORK_UTILS_API bool sha::final() { #else switch (hash_type_) { case ATFRAMEWORK_UTILS_NAMESPACE_ID::hash::sha::EN_ALGORITHM_SHA1: - detail::inner_sha1_finish(inner_obj->sha1_context, inner_obj->output); + internal_sha1_finish(internal_obj->sha1_context, internal_obj->output); return true; case ATFRAMEWORK_UTILS_NAMESPACE_ID::hash::sha::EN_ALGORITHM_SHA224: - detail::inner_sha256_finish(inner_obj->sha224_context, inner_obj->output); + internal_sha256_finish(internal_obj->sha224_context, internal_obj->output); return true; case ATFRAMEWORK_UTILS_NAMESPACE_ID::hash::sha::EN_ALGORITHM_SHA256: - detail::inner_sha256_finish(inner_obj->sha256_context, inner_obj->output); + internal_sha256_finish(internal_obj->sha256_context, internal_obj->output); return true; case ATFRAMEWORK_UTILS_NAMESPACE_ID::hash::sha::EN_ALGORITHM_SHA384: - detail::inner_sha512_finish(inner_obj->sha384_context, inner_obj->output); + internal_sha512_finish(internal_obj->sha384_context, internal_obj->output); return true; case ATFRAMEWORK_UTILS_NAMESPACE_ID::hash::sha::EN_ALGORITHM_SHA512: - detail::inner_sha512_finish(inner_obj->sha512_context, inner_obj->output); + internal_sha512_finish(internal_obj->sha512_context, internal_obj->output); return true; default: break; @@ -1267,14 +1287,13 @@ ATFRAMEWORK_UTILS_API size_t sha::get_output_length(type bt) { #endif } -ATFRAMEWORK_UTILS_API const unsigned char *sha::get_output() const { - return detail::get_output_buffer(private_raw_data_); -} +ATFRAMEWORK_UTILS_API const unsigned char *sha::get_output() const { return get_output_buffer(private_raw_data_); } ATFRAMEWORK_UTILS_API std::string sha::get_output_hex(bool is_uppercase) const { std::string ret; ret.resize(get_output_length() << 1, 0); - ATFRAMEWORK_UTILS_NAMESPACE_ID::string::dumphex(get_output(), get_output_length(), &ret[0], is_uppercase); + ATFRAMEWORK_UTILS_NAMESPACE_ID::string::dumphex(get_output(), get_output_length(), get_writable_string_data(ret), + is_uppercase); return ret; } @@ -1304,7 +1323,7 @@ ATFRAMEWORK_UTILS_API std::string sha::hash_to_hex(type t, const void *in, size_ sha obj; if (false == obj.init(t)) { - return std::string(); + return {}; } obj.update(reinterpret_cast(in), inlen); @@ -1318,7 +1337,7 @@ ATFRAMEWORK_UTILS_API std::string sha::hash_to_base64(type t, const void *in, si sha obj; if (false == obj.init(t)) { - return std::string(); + return {}; } obj.update(reinterpret_cast(in), inlen); @@ -1329,3 +1348,4 @@ ATFRAMEWORK_UTILS_API std::string sha::hash_to_base64(type t, const void *in, si } // namespace hash ATFRAMEWORK_UTILS_NAMESPACE_END +// NOLINTEND(misc-include-cleaner) diff --git a/src/algorithm/xxtea.cpp b/src/algorithm/xxtea.cpp index 8d4ffaa8..c7890b8a 100644 --- a/src/algorithm/xxtea.cpp +++ b/src/algorithm/xxtea.cpp @@ -1,11 +1,16 @@ // Copyright 2026 atframework -#include -#include -#include -#include +// Namespace/API macros are provided by the public header and intentionally used through it here. +// NOLINTBEGIN(misc-include-cleaner) + +#include +#include +#include +#include #include +#include "config/compile_optimize.h" + #include "algorithm/xxtea.h" #define XXTEA_DELTA 0x9e3779b9 @@ -22,36 +27,36 @@ } #endif -#if defined(max) +#ifdef max # undef max #endif ATFRAMEWORK_UTILS_NAMESPACE_BEGIN -namespace detail { +namespace { template -struct xxtea_check_length; +struct ATFW_UTIL_SYMBOL_LOCAL xxtea_check_length; template <> -struct xxtea_check_length { +struct ATFW_UTIL_SYMBOL_LOCAL xxtea_check_length { static bool check_protect(size_t len) { return len > (static_cast(std::numeric_limits::max()) << 2); } }; template -struct xxtea_check_length { +struct ATFW_UTIL_SYMBOL_LOCAL xxtea_check_length { static bool check_protect(size_t) { return false; } }; template -struct xxtea_check_length_delegate { +struct ATFW_UTIL_SYMBOL_LOCAL xxtea_check_length_delegate { static constexpr const bool value = sizeof(Ty) > sizeof(uint32_t); }; -} // namespace detail +} // namespace ATFRAMEWORK_UTILS_API void xxtea_setup(xxtea_key *k, const unsigned char filled[4 * sizeof(uint32_t)]) { - int i; + int i = 0; memset(k->data, 0, sizeof(k->data)); @@ -62,11 +67,11 @@ ATFRAMEWORK_UTILS_API void xxtea_setup(xxtea_key *k, const unsigned char filled[ ATFRAMEWORK_UTILS_API void xxtea_encrypt(const xxtea_key *key, void *buffer, size_t len) { if (len & 0x03) { - abort(); + std::abort(); } - if (detail::xxtea_check_length::value>::check_protect(len)) { - abort(); + if (xxtea_check_length::value>::check_protect(len)) { + std::abort(); } if (nullptr == key || nullptr == buffer || 0 == len) { @@ -76,10 +81,10 @@ ATFRAMEWORK_UTILS_API void xxtea_encrypt(const xxtea_key *key, void *buffer, siz uint32_t *v = reinterpret_cast(buffer); uint32_t n = static_cast(len >> 2); - uint32_t y, z, sum; - uint32_t p, rounds, e; + uint32_t y = 0, z = 0, sum = 0; + uint32_t p = 0, rounds = 0, e = 0; - rounds = 6 + 52 / n; + rounds = 6 + (52 / n); sum = 0; z = v[n - 1]; do { @@ -128,11 +133,11 @@ ATFRAMEWORK_UTILS_API void xxtea_encrypt(const xxtea_key *key, const void *input ATFRAMEWORK_UTILS_API void xxtea_decrypt(const xxtea_key *key, void *buffer, size_t len) { if (len & 0x03) { - abort(); + std::abort(); } - if (detail::xxtea_check_length::value>::check_protect(len)) { - abort(); + if (xxtea_check_length::value>::check_protect(len)) { + std::abort(); } if (nullptr == key || nullptr == buffer || 0 == len) { @@ -142,10 +147,10 @@ ATFRAMEWORK_UTILS_API void xxtea_decrypt(const xxtea_key *key, void *buffer, siz uint32_t *v = reinterpret_cast(buffer); uint32_t n = static_cast(len >> 2); - uint32_t y, z, sum; - uint32_t p, rounds, e; + uint32_t y = 0, z = 0, sum = 0; + uint32_t p = 0, rounds = 0, e = 0; - rounds = 6 + 52 / n; + rounds = 6 + (52 / n); sum = rounds * XXTEA_DELTA; y = v[0]; do { @@ -193,3 +198,4 @@ ATFRAMEWORK_UTILS_API void xxtea_decrypt(const xxtea_key *key, const void *input } ATFRAMEWORK_UTILS_NAMESPACE_END +// NOLINTEND(misc-include-cleaner) diff --git a/test/case/murmur_hash_test.cpp b/test/case/murmur_hash_test.cpp index 0c97a857..d31c6da7 100644 --- a/test/case/murmur_hash_test.cpp +++ b/test/case/murmur_hash_test.cpp @@ -1,5 +1,6 @@ // Copyright 2026 atframework +#include #include #include #include @@ -234,6 +235,68 @@ CASE_TEST(murmur_hash, hash3_x64_128_empty) { // Should not crash } +CASE_TEST(murmur_hash, known_reference_vectors) { + // These known-answer values are compatible with Austin Appleby's SMHasher reference implementation. + // The MurmurHash3_x86_32 vector is also published by scikit-learn: + // murmurhash3_32(b"Hello World!", seed=42) == 3565178 == 0x0036667a. + static constexpr char kPayload[] = "Hello World!"; + static constexpr int kPayloadLength = static_cast(sizeof(kPayload) - 1U); + static constexpr uint32_t kSeed32 = 42U; + static constexpr uint64_t kSeed64 = 42U; + + CASE_EXPECT_EQ(UINT32_C(0x3d9fc202), atfw::util::hash::murmur_hash2(kPayload, kPayloadLength, kSeed32)); + CASE_EXPECT_EQ(UINT64_C(0x22e9f6747266b120), atfw::util::hash::murmur_hash2_64a(kPayload, kPayloadLength, kSeed64)); + CASE_EXPECT_EQ(UINT64_C(0x57236b9bcf30d7cc), atfw::util::hash::murmur_hash2_64b(kPayload, kPayloadLength, kSeed64)); + CASE_EXPECT_EQ(UINT32_C(0x0036667a), atfw::util::hash::murmur_hash3_x86_32(kPayload, kPayloadLength, kSeed32)); + + uint32_t x86_128[4] = {0}; + atfw::util::hash::murmur_hash3_x86_128(kPayload, kPayloadLength, kSeed32, x86_128); + CASE_EXPECT_EQ(UINT32_C(0x7f188edf), x86_128[0]); + CASE_EXPECT_EQ(UINT32_C(0x42a77b58), x86_128[1]); + CASE_EXPECT_EQ(UINT32_C(0xb6161cc7), x86_128[2]); + CASE_EXPECT_EQ(UINT32_C(0x9359780e), x86_128[3]); + + uint64_t x64_128[2] = {0}; + atfw::util::hash::murmur_hash3_x64_128(kPayload, kPayloadLength, kSeed32, x64_128); + CASE_EXPECT_EQ(UINT64_C(0xa7bc102ca798f8dc), x64_128[0]); + CASE_EXPECT_EQ(UINT64_C(0x3c957070a5f9fa3e), x64_128[1]); +} + +CASE_TEST(murmur_hash, unaligned_input_matches_aligned) { + static constexpr char kPayload[] = "0123456789abcdef0123456789abcdef"; + static constexpr int kPayloadLength = static_cast(sizeof(kPayload) - 1U); + + alignas(8) unsigned char aligned_storage[sizeof(kPayload)] = {0}; + std::memcpy(aligned_storage, kPayload, static_cast(kPayloadLength)); + + std::vector unaligned_storage(static_cast(kPayloadLength) + 1U, 0); + std::memcpy(unaligned_storage.data() + 1U, kPayload, static_cast(kPayloadLength)); + + const void *aligned_key = aligned_storage; + const void *unaligned_key = unaligned_storage.data() + 1U; + + CASE_EXPECT_EQ(atfw::util::hash::murmur_hash2(aligned_key, kPayloadLength, 0), + atfw::util::hash::murmur_hash2(unaligned_key, kPayloadLength, 0)); + CASE_EXPECT_EQ(atfw::util::hash::murmur_hash2_64a(aligned_key, kPayloadLength, 0), + atfw::util::hash::murmur_hash2_64a(unaligned_key, kPayloadLength, 0)); + CASE_EXPECT_EQ(atfw::util::hash::murmur_hash2_64b(aligned_key, kPayloadLength, 0), + atfw::util::hash::murmur_hash2_64b(unaligned_key, kPayloadLength, 0)); + CASE_EXPECT_EQ(atfw::util::hash::murmur_hash3_x86_32(aligned_key, kPayloadLength, 0), + atfw::util::hash::murmur_hash3_x86_32(unaligned_key, kPayloadLength, 0)); + + uint32_t aligned_x86_128[4] = {0}; + uint32_t unaligned_x86_128[4] = {0}; + atfw::util::hash::murmur_hash3_x86_128(aligned_key, kPayloadLength, 0, aligned_x86_128); + atfw::util::hash::murmur_hash3_x86_128(unaligned_key, kPayloadLength, 0, unaligned_x86_128); + CASE_EXPECT_EQ(0, std::memcmp(aligned_x86_128, unaligned_x86_128, sizeof(aligned_x86_128))); + + uint64_t aligned_x64_128[2] = {0}; + uint64_t unaligned_x64_128[2] = {0}; + atfw::util::hash::murmur_hash3_x64_128(aligned_key, kPayloadLength, 0, aligned_x64_128); + atfw::util::hash::murmur_hash3_x64_128(unaligned_key, kPayloadLength, 0, unaligned_x64_128); + CASE_EXPECT_EQ(0, std::memcmp(aligned_x64_128, unaligned_x64_128, sizeof(aligned_x64_128))); +} + CASE_TEST(murmur_hash, hash2_distribution) { // Test distribution by hashing sequential integers const int num_buckets = 64; From 80e2b38e61ff6793dfa15587a9ee845e7809f6c3 Mon Sep 17 00:00:00 2001 From: owent Date: Thu, 14 May 2026 18:35:18 +0800 Subject: [PATCH 2/2] =?UTF-8?q?=E4=BC=98=E5=8C=96=E7=AE=97=E6=B3=95?= =?UTF-8?q?=E5=BA=93=E7=9A=84=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CMakeLists.txt | 1 - src/algorithm/compression.cpp | 8 ++++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 371896ed..1167febf 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -42,7 +42,6 @@ include("${CMAKE_CURRENT_LIST_DIR}/project/cmake/ProjectBuildOption.cmake") # Link RPATH set(CMAKE_INSTALL_RPATH_USE_LINK_PATH YES) -set(CMAKE_BUILD_WITH_INSTALL_RPATH NO) set(CMAKE_BUILD_RPATH_USE_ORIGIN YES) set(ATFRAMEWORK_UTILS_VERSION_MAJOR "${PROJECT_VERSION_MAJOR}") diff --git a/src/algorithm/compression.cpp b/src/algorithm/compression.cpp index a63a3ff9..b0c9aacb 100644 --- a/src/algorithm/compression.cpp +++ b/src/algorithm/compression.cpp @@ -41,13 +41,17 @@ static constexpr T _numeric_limits_max() noexcept { } static bool _resize_output(std::vector& output, size_t size) noexcept { +# if defined(ATFRAMEWORK_UTILS_ENABLE_EXCEPTION) && ATFRAMEWORK_UTILS_ENABLE_EXCEPTION try { +# endif output.resize(size); return true; +# if defined(ATFRAMEWORK_UTILS_ENABLE_EXCEPTION) && ATFRAMEWORK_UTILS_ENABLE_EXCEPTION } catch (...) { output.clear(); return false; } +# endif } static bool _size_to_int(size_t input, int& output) noexcept { @@ -352,7 +356,9 @@ ATFRAMEWORK_UTILS_API bool is_algorithm_supported(algorithm_t type) noexcept { ATFRAMEWORK_UTILS_API std::vector get_supported_algorithms() noexcept { std::vector result; +# if defined(ATFRAMEWORK_UTILS_ENABLE_EXCEPTION) && ATFRAMEWORK_UTILS_ENABLE_EXCEPTION try { +# endif result.reserve(4); # if defined(ATFW_UTIL_MACRO_COMPRESSION_ZSTD) result.push_back(algorithm_t::kZstd); @@ -366,9 +372,11 @@ ATFRAMEWORK_UTILS_API std::vector get_supported_algorithms() noexce # if defined(ATFW_UTIL_MACRO_COMPRESSION_ZLIB) result.push_back(algorithm_t::kZlib); # endif +# if defined(ATFRAMEWORK_UTILS_ENABLE_EXCEPTION) && ATFRAMEWORK_UTILS_ENABLE_EXCEPTION } catch (...) { result.clear(); } +# endif return result; }