From cb813a7765162577bd67af6dec0140a86ea18ad9 Mon Sep 17 00:00:00 2001 From: Pavel Novikov Date: Sat, 27 Dec 2025 00:04:28 +0300 Subject: [PATCH 1/3] fixed UB --- include/fast_float/ascii_number.h | 40 ++++++++++++++++--------------- 1 file changed, 21 insertions(+), 19 deletions(-) diff --git a/include/fast_float/ascii_number.h b/include/fast_float/ascii_number.h index 6208ef2..4e1ce3a 100644 --- a/include/fast_float/ascii_number.h +++ b/include/fast_float/ascii_number.h @@ -523,33 +523,36 @@ parse_int_string(UC const *p, UC const *pend, T &value, return answer; } - union { - uint8_t as_str[4]; - uint32_t as_int; - } digits; + uint32_t digits; - if (cpp20_and_in_constexpr()) { - digits.as_int = 0; +#if FASTFLOAT_HAS_IS_CONSTANT_EVALUATED && FASTFLOAT_HAS_BIT_CAST + if (std::is_constant_evaluated()) { + uint8_t str[4]{}; for (size_t j = 0; j < 4 && j < len; ++j) { - digits.as_str[j] = static_cast(p[j]); + str[j] = static_cast(p[j]); } - } else if (len >= 4) { - memcpy(&digits.as_int, p, 4); + digits = std::bit_cast(str); + } +#else + if (false) { + } +#endif + else if (len >= 4) { + ::memcpy(&digits, p, 4); } else { uint32_t b0 = static_cast(p[0]); uint32_t b1 = (len > 1) ? static_cast(p[1]) : 0xFFu; uint32_t b2 = (len > 2) ? static_cast(p[2]) : 0xFFu; uint32_t b3 = 0xFFu; #if FASTFLOAT_IS_BIG_ENDIAN - digits.as_int = (b0 << 24) | (b1 << 16) | (b2 << 8) | b3; + digits = (b0 << 24) | (b1 << 16) | (b2 << 8) | b3; #else - digits.as_int = b0 | (b1 << 8) | (b2 << 16) | (b3 << 24); + digits = b0 | (b1 << 8) | (b2 << 16) | (b3 << 24); #endif } uint32_t magic = - ((digits.as_int + 0x46464646u) | (digits.as_int - 0x30303030u)) & - 0x80808080u; + ((digits + 0x46464646u) | (digits - 0x30303030u)) & 0x80808080u; uint32_t tz = (uint32_t)countr_zero_32(magic); // 7, 15, 23, 31, or 32 uint32_t nd = (tz == 32) ? 4 : (tz >> 3); nd = (uint32_t)std::min((size_t)nd, len); @@ -578,18 +581,17 @@ parse_int_string(UC const *p, UC const *pend, T &value, return answer; } - digits.as_int ^= 0x30303030u; - digits.as_int <<= ((4 - nd) * 8); + digits ^= 0x30303030u; + digits <<= ((4 - nd) * 8); - uint32_t check = ((digits.as_int >> 24) & 0xff) | - ((digits.as_int >> 8) & 0xff00) | - ((digits.as_int << 8) & 0xff0000); + uint32_t check = ((digits >> 24) & 0xff) | ((digits >> 8) & 0xff00) | + ((digits << 8) & 0xff0000); if (check > 0x00020505) { answer.ec = std::errc::result_out_of_range; answer.ptr = p + nd; return answer; } - value = (uint8_t)((0x640a01 * digits.as_int) >> 24); + value = (uint8_t)((0x640a01 * digits) >> 24); answer.ec = std::errc(); answer.ptr = p + nd; return answer; From b4d26ec866fe688af148d128c5ef8b8e98823a41 Mon Sep 17 00:00:00 2001 From: Daniel Lemire Date: Sat, 27 Dec 2025 12:06:36 -0500 Subject: [PATCH 2/3] v8.1.1 --- CMakeLists.txt | 2 +- README.md | 6 +++--- include/fast_float/float_common.h | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 645fce7..99c322b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,7 +1,7 @@ cmake_minimum_required(VERSION 3.14) -project(fast_float VERSION 8.1.0 LANGUAGES CXX) +project(fast_float VERSION 8.1.1 LANGUAGES CXX) set(FASTFLOAT_CXX_STANDARD 11 CACHE STRING "the C++ standard to use for fastfloat") set(CMAKE_CXX_STANDARD ${FASTFLOAT_CXX_STANDARD}) option(FASTFLOAT_TEST "Enable tests" OFF) diff --git a/README.md b/README.md index b039e63..f9a5264 100644 --- a/README.md +++ b/README.md @@ -533,7 +533,7 @@ sufficiently recent version of CMake (3.11 or better at least): FetchContent_Declare( fast_float GIT_REPOSITORY https://github.com/fastfloat/fast_float.git - GIT_TAG tags/v8.1.0 + GIT_TAG tags/v8.1.1 GIT_SHALLOW TRUE) FetchContent_MakeAvailable(fast_float) @@ -549,7 +549,7 @@ You may also use [CPM](https://github.com/cpm-cmake/CPM.cmake), like so: CPMAddPackage( NAME fast_float GITHUB_REPOSITORY "fastfloat/fast_float" - GIT_TAG v8.1.0) + GIT_TAG v8.1.1) ``` ## Using as single header @@ -561,7 +561,7 @@ if desired as described in the command line help. You may directly download automatically generated single-header files: - + ## Benchmarking diff --git a/include/fast_float/float_common.h b/include/fast_float/float_common.h index ab95e1d..f1c5469 100644 --- a/include/fast_float/float_common.h +++ b/include/fast_float/float_common.h @@ -17,7 +17,7 @@ #define FASTFLOAT_VERSION_MAJOR 8 #define FASTFLOAT_VERSION_MINOR 1 -#define FASTFLOAT_VERSION_PATCH 0 +#define FASTFLOAT_VERSION_PATCH 1 #define FASTFLOAT_STRINGIZE_IMPL(x) #x #define FASTFLOAT_STRINGIZE(x) FASTFLOAT_STRINGIZE_IMPL(x) From dd77fb5e4c3339725775fd61e51034a5e5a55cbb Mon Sep 17 00:00:00 2001 From: Daniel Lemire Date: Sat, 27 Dec 2025 12:08:58 -0500 Subject: [PATCH 3/3] v8.2.0 --- CMakeLists.txt | 2 +- README.md | 6 +++--- include/fast_float/float_common.h | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 99c322b..f1f7a4a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,7 +1,7 @@ cmake_minimum_required(VERSION 3.14) -project(fast_float VERSION 8.1.1 LANGUAGES CXX) +project(fast_float VERSION 8.2.0 LANGUAGES CXX) set(FASTFLOAT_CXX_STANDARD 11 CACHE STRING "the C++ standard to use for fastfloat") set(CMAKE_CXX_STANDARD ${FASTFLOAT_CXX_STANDARD}) option(FASTFLOAT_TEST "Enable tests" OFF) diff --git a/README.md b/README.md index f9a5264..be21066 100644 --- a/README.md +++ b/README.md @@ -533,7 +533,7 @@ sufficiently recent version of CMake (3.11 or better at least): FetchContent_Declare( fast_float GIT_REPOSITORY https://github.com/fastfloat/fast_float.git - GIT_TAG tags/v8.1.1 + GIT_TAG tags/v8.2.0 GIT_SHALLOW TRUE) FetchContent_MakeAvailable(fast_float) @@ -549,7 +549,7 @@ You may also use [CPM](https://github.com/cpm-cmake/CPM.cmake), like so: CPMAddPackage( NAME fast_float GITHUB_REPOSITORY "fastfloat/fast_float" - GIT_TAG v8.1.1) + GIT_TAG v8.2.0) ``` ## Using as single header @@ -561,7 +561,7 @@ if desired as described in the command line help. You may directly download automatically generated single-header files: - + ## Benchmarking diff --git a/include/fast_float/float_common.h b/include/fast_float/float_common.h index f1c5469..62fe2bf 100644 --- a/include/fast_float/float_common.h +++ b/include/fast_float/float_common.h @@ -16,8 +16,8 @@ #include "constexpr_feature_detect.h" #define FASTFLOAT_VERSION_MAJOR 8 -#define FASTFLOAT_VERSION_MINOR 1 -#define FASTFLOAT_VERSION_PATCH 1 +#define FASTFLOAT_VERSION_MINOR 2 +#define FASTFLOAT_VERSION_PATCH 0 #define FASTFLOAT_STRINGIZE_IMPL(x) #x #define FASTFLOAT_STRINGIZE(x) FASTFLOAT_STRINGIZE_IMPL(x)