diff --git a/.github/workflows/fuzz.yml b/.github/workflows/fuzz.yml index 4487018fe..7b39766c8 100644 --- a/.github/workflows/fuzz.yml +++ b/.github/workflows/fuzz.yml @@ -86,6 +86,26 @@ jobs: - "deb http://apt.llvm.org/jammy/ llvm-toolchain-jammy-17 main" source_keys: - "https://apt.llvm.org/llvm-snapshot.gpg.key" + - toolset: clang + compiler: clang++-18 + cxxstd: "14,17,20,23" + os: ubuntu-24.04 + install: + - clang-18 + sources: + - "deb http://apt.llvm.org/noble/ llvm-toolchain-noble-18 main" + source_keys: + - "https://apt.llvm.org/llvm-snapshot.gpg.key" + - toolset: clang + compiler: clang++-19 + cxxstd: "14,17,20,23" + os: ubuntu-24.04 + install: + - clang-19 + sources: + - "deb http://apt.llvm.org/noble/ llvm-toolchain-noble-19 main" + source_keys: + - "https://apt.llvm.org/llvm-snapshot.gpg.key" timeout-minutes: 60 diff --git a/fuzzing/fuzz_from_chars_float.cpp b/fuzzing/fuzz_from_chars_float.cpp index 68ab03428..bcb8e26d2 100644 --- a/fuzzing/fuzz_from_chars_float.cpp +++ b/fuzzing/fuzz_from_chars_float.cpp @@ -26,6 +26,36 @@ extern "C" int LLVMFuzzerTestOneInput(const std::uint8_t* data, std::size_t size boost::decimal::decimal128 ld_val; boost::decimal::from_chars(c_data, c_data + size, ld_val, format); } + + // Now with strings + const auto c_data_str = std::string(c_data, size); + for (const auto format : formats) + { + boost::decimal::decimal32 f_val; + boost::decimal::from_chars(c_data_str, f_val, format); + + boost::decimal::decimal64 val; + boost::decimal::from_chars(c_data_str, val, format); + + boost::decimal::decimal128 ld_val; + boost::decimal::from_chars(c_data_str, ld_val, format); + } + + // And string views as applicable + #ifdef BOOST_DECIMAL_HAS_STD_STRING_VIEW + const auto c_data_str_view = std::string_view(c_data_str); + for (const auto format : formats) + { + boost::decimal::decimal32 f_val; + boost::decimal::from_chars(c_data_str_view, f_val, format); + + boost::decimal::decimal64 val; + boost::decimal::from_chars(c_data_str_view, val, format); + + boost::decimal::decimal128 ld_val; + boost::decimal::from_chars(c_data_str_view, ld_val, format); + } + #endif } catch(...) { diff --git a/fuzzing/old_crashes/fuzz_from_chars_float/crash-da39a3ee5e6b4b0d3255bfef95601890afd80709 b/fuzzing/old_crashes/fuzz_from_chars_float/crash-da39a3ee5e6b4b0d3255bfef95601890afd80709 new file mode 100644 index 000000000..e69de29bb diff --git a/include/boost/decimal/literals.hpp b/include/boost/decimal/literals.hpp index 73d55540f..7ae4e3987 100644 --- a/include/boost/decimal/literals.hpp +++ b/include/boost/decimal/literals.hpp @@ -18,232 +18,233 @@ #include #endif -namespace boost { namespace decimal { +namespace boost { +namespace decimal { -BOOST_DECIMAL_EXPORT constexpr auto operator "" _DF(const char* str) -> decimal32 +BOOST_DECIMAL_EXPORT constexpr auto operator ""_DF(const char* str) -> decimal32 { decimal32 d; from_chars(str, str + detail::strlen(str), d); return d; } -BOOST_DECIMAL_EXPORT constexpr auto operator "" _df(const char* str) -> decimal32 +BOOST_DECIMAL_EXPORT constexpr auto operator ""_df(const char* str) -> decimal32 { decimal32 d; from_chars(str, str + detail::strlen(str), d); return d; } -BOOST_DECIMAL_EXPORT constexpr auto operator "" _DF(const char* str, std::size_t len) -> decimal32 +BOOST_DECIMAL_EXPORT constexpr auto operator ""_DF(const char* str, std::size_t len) -> decimal32 { decimal32 d; from_chars(str, str + len, d); return d; } -BOOST_DECIMAL_EXPORT constexpr auto operator "" _df(const char* str, std::size_t len) -> decimal32 +BOOST_DECIMAL_EXPORT constexpr auto operator ""_df(const char* str, std::size_t len) -> decimal32 { decimal32 d; from_chars(str, str + len, d); return d; } -BOOST_DECIMAL_EXPORT constexpr auto operator "" _DF(unsigned long long v) -> decimal32 +BOOST_DECIMAL_EXPORT constexpr auto operator ""_DF(unsigned long long v) -> decimal32 { return decimal32{v}; } -BOOST_DECIMAL_EXPORT constexpr auto operator "" _df(unsigned long long v) -> decimal32 +BOOST_DECIMAL_EXPORT constexpr auto operator ""_df(unsigned long long v) -> decimal32 { return decimal32{v}; } -BOOST_DECIMAL_EXPORT constexpr auto operator "" _DFF(const char* str) -> decimal32_fast +BOOST_DECIMAL_EXPORT constexpr auto operator ""_DFF(const char* str) -> decimal32_fast { decimal32_fast d; from_chars(str, str + detail::strlen(str), d); return d; } -BOOST_DECIMAL_EXPORT constexpr auto operator "" _dff(const char* str) -> decimal32_fast +BOOST_DECIMAL_EXPORT constexpr auto operator ""_dff(const char* str) -> decimal32_fast { decimal32_fast d; from_chars(str, str + detail::strlen(str), d); return d; } -BOOST_DECIMAL_EXPORT constexpr auto operator "" _DFF(const char* str, std::size_t len) -> decimal32_fast +BOOST_DECIMAL_EXPORT constexpr auto operator ""_DFF(const char* str, std::size_t len) -> decimal32_fast { decimal32_fast d; from_chars(str, str + len, d); return d; } -BOOST_DECIMAL_EXPORT constexpr auto operator "" _dff(const char* str, std::size_t len) -> decimal32_fast +BOOST_DECIMAL_EXPORT constexpr auto operator ""_dff(const char* str, std::size_t len) -> decimal32_fast { decimal32_fast d; from_chars(str, str + len, d); return d; } -BOOST_DECIMAL_EXPORT constexpr auto operator "" _DFF(unsigned long long v) -> decimal32_fast +BOOST_DECIMAL_EXPORT constexpr auto operator ""_DFF(unsigned long long v) -> decimal32_fast { return decimal32_fast{v}; } -BOOST_DECIMAL_EXPORT constexpr auto operator "" _dff(unsigned long long v) -> decimal32_fast +BOOST_DECIMAL_EXPORT constexpr auto operator ""_dff(unsigned long long v) -> decimal32_fast { return decimal32_fast{v}; } -BOOST_DECIMAL_EXPORT constexpr auto operator "" _DD(const char* str) -> decimal64 +BOOST_DECIMAL_EXPORT constexpr auto operator ""_DD(const char* str) -> decimal64 { decimal64 d; from_chars(str, str + detail::strlen(str), d); return d; } -BOOST_DECIMAL_EXPORT constexpr auto operator "" _dd(const char* str) -> decimal64 +BOOST_DECIMAL_EXPORT constexpr auto operator ""_dd(const char* str) -> decimal64 { decimal64 d; from_chars(str, str + detail::strlen(str), d); return d; } -BOOST_DECIMAL_EXPORT constexpr auto operator "" _DD(const char* str, std::size_t) -> decimal64 +BOOST_DECIMAL_EXPORT constexpr auto operator ""_DD(const char* str, std::size_t) -> decimal64 { decimal64 d; from_chars(str, str + detail::strlen(str), d); return d; } -BOOST_DECIMAL_EXPORT constexpr auto operator "" _dd(const char* str, std::size_t) -> decimal64 +BOOST_DECIMAL_EXPORT constexpr auto operator ""_dd(const char* str, std::size_t) -> decimal64 { decimal64 d; from_chars(str, str + detail::strlen(str), d); return d; } -BOOST_DECIMAL_EXPORT constexpr auto operator "" _DD(unsigned long long v) -> decimal64 +BOOST_DECIMAL_EXPORT constexpr auto operator ""_DD(unsigned long long v) -> decimal64 { return decimal64{v}; } -BOOST_DECIMAL_EXPORT constexpr auto operator "" _dd(unsigned long long v) -> decimal64 +BOOST_DECIMAL_EXPORT constexpr auto operator ""_dd(unsigned long long v) -> decimal64 { return decimal64{v}; } -BOOST_DECIMAL_EXPORT constexpr auto operator "" _DDF(const char* str) -> decimal64_fast +BOOST_DECIMAL_EXPORT constexpr auto operator ""_DDF(const char* str) -> decimal64_fast { decimal64_fast d; from_chars(str, str + detail::strlen(str), d); return d; } -BOOST_DECIMAL_EXPORT constexpr auto operator "" _ddf(const char* str) -> decimal64_fast +BOOST_DECIMAL_EXPORT constexpr auto operator ""_ddf(const char* str) -> decimal64_fast { decimal64_fast d; from_chars(str, str + detail::strlen(str), d); return d; } -BOOST_DECIMAL_EXPORT constexpr auto operator "" _DDF(const char* str, std::size_t len) -> decimal64_fast +BOOST_DECIMAL_EXPORT constexpr auto operator ""_DDF(const char* str, std::size_t len) -> decimal64_fast { decimal64_fast d; from_chars(str, str + len, d); return d; } -BOOST_DECIMAL_EXPORT constexpr auto operator "" _ddf(const char* str, std::size_t len) -> decimal64_fast +BOOST_DECIMAL_EXPORT constexpr auto operator ""_ddf(const char* str, std::size_t len) -> decimal64_fast { decimal64_fast d; from_chars(str, str + len, d); return d; } -BOOST_DECIMAL_EXPORT constexpr auto operator "" _DDF(unsigned long long v) -> decimal64_fast +BOOST_DECIMAL_EXPORT constexpr auto operator ""_DDF(unsigned long long v) -> decimal64_fast { return decimal64_fast{v}; } -BOOST_DECIMAL_EXPORT constexpr auto operator "" _ddf(unsigned long long v) -> decimal64_fast +BOOST_DECIMAL_EXPORT constexpr auto operator ""_ddf(unsigned long long v) -> decimal64_fast { return decimal64_fast{v}; } -BOOST_DECIMAL_EXPORT constexpr auto operator "" _DL(const char* str) -> decimal128 +BOOST_DECIMAL_EXPORT constexpr auto operator ""_DL(const char* str) -> decimal128 { decimal128 d; from_chars(str, str + detail::strlen(str), d); return d; } -BOOST_DECIMAL_EXPORT constexpr auto operator "" _dl(const char* str) -> decimal128 +BOOST_DECIMAL_EXPORT constexpr auto operator ""_dl(const char* str) -> decimal128 { decimal128 d; from_chars(str, str + detail::strlen(str), d); return d; } -BOOST_DECIMAL_EXPORT constexpr auto operator "" _DL(const char* str, std::size_t) -> decimal128 +BOOST_DECIMAL_EXPORT constexpr auto operator ""_DL(const char* str, std::size_t) -> decimal128 { decimal128 d; from_chars(str, str + detail::strlen(str), d); return d; } -BOOST_DECIMAL_EXPORT constexpr auto operator "" _dl(const char* str, std::size_t) -> decimal128 +BOOST_DECIMAL_EXPORT constexpr auto operator ""_dl(const char* str, std::size_t) -> decimal128 { decimal128 d; from_chars(str, str + detail::strlen(str), d); return d; } -BOOST_DECIMAL_EXPORT constexpr auto operator "" _DL(unsigned long long v) -> decimal128 +BOOST_DECIMAL_EXPORT constexpr auto operator ""_DL(unsigned long long v) -> decimal128 { return decimal128{v}; } -BOOST_DECIMAL_EXPORT constexpr auto operator "" _dl(unsigned long long v) -> decimal128 +BOOST_DECIMAL_EXPORT constexpr auto operator ""_dl(unsigned long long v) -> decimal128 { return decimal128{v}; } -BOOST_DECIMAL_EXPORT constexpr auto operator "" _DLF(const char* str) -> decimal128_fast +BOOST_DECIMAL_EXPORT constexpr auto operator ""_DLF(const char* str) -> decimal128_fast { decimal128_fast d; from_chars(str, str + detail::strlen(str), d); return d; } -BOOST_DECIMAL_EXPORT constexpr auto operator "" _dlf(const char* str) -> decimal128_fast +BOOST_DECIMAL_EXPORT constexpr auto operator ""_dlf(const char* str) -> decimal128_fast { decimal128_fast d; from_chars(str, str + detail::strlen(str), d); return d; } -BOOST_DECIMAL_EXPORT constexpr auto operator "" _DLF(const char* str, std::size_t len) -> decimal128_fast +BOOST_DECIMAL_EXPORT constexpr auto operator ""_DLF(const char* str, std::size_t len) -> decimal128_fast { decimal128_fast d; from_chars(str, str + len, d); return d; } -BOOST_DECIMAL_EXPORT constexpr auto operator "" _dlf(const char* str, std::size_t len) -> decimal128_fast +BOOST_DECIMAL_EXPORT constexpr auto operator ""_dlf(const char* str, std::size_t len) -> decimal128_fast { decimal128_fast d; from_chars(str, str + len, d); return d; } -BOOST_DECIMAL_EXPORT constexpr auto operator "" _DLF(unsigned long long v) -> decimal128_fast +BOOST_DECIMAL_EXPORT constexpr auto operator ""_DLF(unsigned long long v) -> decimal128_fast { return decimal128_fast{v}; } -BOOST_DECIMAL_EXPORT constexpr auto operator "" _dlf(unsigned long long v) -> decimal128_fast +BOOST_DECIMAL_EXPORT constexpr auto operator ""_dlf(unsigned long long v) -> decimal128_fast { return decimal128_fast{v}; } diff --git a/test/test_from_chars.cpp b/test/test_from_chars.cpp index 0500a29f7..cc0a8ec02 100644 --- a/test/test_from_chars.cpp +++ b/test/test_from_chars.cpp @@ -325,9 +325,20 @@ void test_string_interface() constexpr T correct_val {42}; std::string str {"42"}; T val; - const auto r = from_chars(str, val); + auto r = from_chars(str, val); BOOST_TEST(r); BOOST_TEST_EQ(val, correct_val); + + // Empty string + std::string empty; + r = from_chars(empty, val); + BOOST_TEST(r.ec == std::errc::invalid_argument); + + #ifdef BOOST_DECIMAL_HAS_STD_STRING_VIEW + std::string_view empty_view = std::string_view(empty); + r = from_chars(empty_view, val); + BOOST_TEST(r.ec == std::errc::invalid_argument); + #endif } int main()