diff --git a/fuzzing/Jamfile b/fuzzing/Jamfile index 31dda6a58..7341af662 100644 --- a/fuzzing/Jamfile +++ b/fuzzing/Jamfile @@ -36,7 +36,7 @@ toolset.flags $(__name__).make-corpus PYTHON ; for local fuzzer in $(all_fuzzers) { - local fuzz_time = 60 ; + local fuzz_time = 30 ; local corpus = /tmp/corpus/$(fuzzer) ; local min_corpus = /tmp/mincorpus/$(fuzzer) ; local seed_corpus = $(HERE)/seedcorpus/$(fuzzer) ; diff --git a/include/boost/decimal/charconv.hpp b/include/boost/decimal/charconv.hpp index cc17272ce..3ec1c90d2 100644 --- a/include/boost/decimal/charconv.hpp +++ b/include/boost/decimal/charconv.hpp @@ -542,16 +542,16 @@ BOOST_DECIMAL_CONSTEXPR auto to_chars_fixed_impl(char* first, char* last, const { append_trailing_zeros = true; } + } - // In general formatting we remove trailing 0s - if (fmt == chars_format::general) - { - - const auto zeros_removal {remove_trailing_zeros(significand)}; - significand = zeros_removal.trimmed_number; - exponent += static_cast(zeros_removal.number_of_removed_zeros); - num_dig -= static_cast(zeros_removal.number_of_removed_zeros); - } + // In general formatting we remove trailing 0s + // Same with unspecified precision fixed formatting + if ((precision == -1 && fmt == chars_format::fixed) || fmt == chars_format::general) + { + const auto zeros_removal {remove_trailing_zeros(significand)}; + significand = zeros_removal.trimmed_number; + exponent += static_cast(zeros_removal.number_of_removed_zeros); + num_dig -= static_cast(zeros_removal.number_of_removed_zeros); } // Make sure the result will fit in the buffer @@ -569,25 +569,32 @@ BOOST_DECIMAL_CONSTEXPR auto to_chars_fixed_impl(char* first, char* last, const *first++ = '0'; return {first, std::errc()}; } - else if (num_leading_zeros > precision) + else if (precision != -1 && num_leading_zeros > precision) { *first++ = '0'; *first++ = '.'; - std::memset(first, '0', static_cast(precision)); + boost::decimal::detail::memset(first, '0', static_cast(precision)); return {first + precision, std::errc()}; } else { *first++ = '0'; *first++ = '.'; - std::memset(first, '0', static_cast(num_leading_zeros)); + boost::decimal::detail::memset(first, '0', static_cast(num_leading_zeros)); first += num_leading_zeros; // We can skip the rest if there's nothing more to do for the required precision if (significand == 0) { - std::memset(first, '0', static_cast(precision - num_leading_zeros)); - return {first + precision, std::errc()}; + if (precision - num_leading_zeros > 0) + { + boost::decimal::detail::memset(first, '0', static_cast(precision - num_leading_zeros)); + return {first + precision, std::errc()}; + } + else + { + return {first, std::errc()}; + } } } } diff --git a/include/boost/decimal/detail/memcpy.hpp b/include/boost/decimal/detail/memcpy.hpp index 49f19e198..bfd8edd27 100644 --- a/include/boost/decimal/detail/memcpy.hpp +++ b/include/boost/decimal/detail/memcpy.hpp @@ -23,6 +23,7 @@ #if defined(__GNUC__) && __GNUC__ >= 10 # pragma GCC diagnostic push # pragma GCC diagnostic ignored "-Wstringop-overflow" +# pragma GCC diagnostic ignored "-Warray-bounds" # define BOOST_DECIMAL_STRINGOP_OVERFLOW_DISABLED #endif diff --git a/test/Jamfile b/test/Jamfile index d67baeb4f..763173f66 100644 --- a/test/Jamfile +++ b/test/Jamfile @@ -45,6 +45,7 @@ project : requirements run-fail benchmarks.cpp ; run compare_dec128_and_fast.cpp ; compile-fail concepts_test.cpp ; +run crash_report_1.cpp ; run github_issue_426.cpp ; run github_issue_448.cpp ; run-fail github_issue_519.cpp ; diff --git a/test/crash_report_1.cpp b/test/crash_report_1.cpp new file mode 100644 index 000000000..bc8f4b162 --- /dev/null +++ b/test/crash_report_1.cpp @@ -0,0 +1,27 @@ +// Copyright 2025 Matt Borland +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +#include +#include +#include + +using namespace boost::decimal; + +int main() +{ + char buffer[64]{}; + const auto print_val {0.000001_df}; + + const auto r = boost::decimal::to_chars( + buffer, + buffer + sizeof(buffer), + print_val, + boost::decimal::chars_format::fixed + ); + *r.ptr = '\0'; + + BOOST_TEST_CSTR_EQ(buffer, "0.000001"); + + return boost::report_errors(); +} diff --git a/test/test_to_chars.cpp b/test/test_to_chars.cpp index 88eb681ab..ac60bf8b2 100644 --- a/test/test_to_chars.cpp +++ b/test/test_to_chars.cpp @@ -23,7 +23,7 @@ static constexpr auto N = static_cast(1024U >> 4U); // Number of tr #if !defined(BOOST_DECIMAL_DISABLE_CLIB) && !(defined(__GNUC__) && __GNUC__ >= 13 && !defined(__aarch64__)) template -void test_value(T val, const char* result, chars_format fmt, int precision = -1) +void test_value(T val, const char* result, chars_format fmt, int precision) { char buffer[256] {}; auto r = to_chars(buffer, buffer + sizeof(buffer), val, fmt, precision); @@ -32,6 +32,16 @@ void test_value(T val, const char* result, chars_format fmt, int precision = -1) BOOST_TEST_CSTR_EQ(result, buffer); } +template +void test_value(T val, const char* result, chars_format fmt) +{ + char buffer[256] {}; + auto r = to_chars(buffer, buffer + sizeof(buffer), val, fmt); + *r.ptr = '\0'; + BOOST_TEST(r); + BOOST_TEST_CSTR_EQ(result, buffer); +} + template void test_value(T val, const char* result) { @@ -764,6 +774,25 @@ void test_777() test_value(value3, "-2111000000", chars_format::fixed, 0); } +template +void test_more_powers_10() +{ + test_value(T{1, -6}, "0.000001", chars_format::fixed); + test_value(T{1, -5}, "0.00001", chars_format::fixed); + test_value(T{1, -4}, "0.0001", chars_format::fixed); + test_value(T{1, -3}, "0.001", chars_format::fixed); + test_value(T{1, -2}, "0.01", chars_format::fixed); + test_value(T{1, -1}, "0.1", chars_format::fixed); + test_value(T{1, 0}, "1", chars_format::fixed); + test_value(T{1, 1}, "10", chars_format::fixed); + test_value(T{1, 2}, "100", chars_format::fixed); + test_value(T{1, 3}, "1000", chars_format::fixed); + test_value(T{1, 4}, "10000", chars_format::fixed); + test_value(T{1, 5}, "100000", chars_format::fixed); + test_value(T{1, 6}, "1000000", chars_format::fixed); + test_value(T{1, 7}, "10000000", chars_format::fixed); +} + int main() { test_non_finite_values(); @@ -874,6 +903,10 @@ int main() test_777(); test_777(); + test_more_powers_10(); + test_more_powers_10(); + test_more_powers_10(); + return boost::report_errors(); }