Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion fuzzing/Jamfile
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ toolset.flags $(__name__).make-corpus PYTHON <python.interpreter> ;

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) ;
Expand Down
35 changes: 21 additions & 14 deletions include/boost/decimal/charconv.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -542,16 +542,16 @@
{
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<int>(zeros_removal.number_of_removed_zeros);
num_dig -= static_cast<int>(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<int>(zeros_removal.number_of_removed_zeros);
num_dig -= static_cast<int>(zeros_removal.number_of_removed_zeros);
}

// Make sure the result will fit in the buffer
Expand All @@ -569,25 +569,32 @@
*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<std::size_t>(precision));
boost::decimal::detail::memset(first, '0', static_cast<std::size_t>(precision));

Check warning on line 576 in include/boost/decimal/charconv.hpp

View check run for this annotation

Codecov / codecov/patch

include/boost/decimal/charconv.hpp#L576

Added line #L576 was not covered by tests
return {first + precision, std::errc()};
}
else
{
*first++ = '0';
*first++ = '.';
std::memset(first, '0', static_cast<std::size_t>(num_leading_zeros));
boost::decimal::detail::memset(first, '0', static_cast<std::size_t>(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<std::size_t>(precision - num_leading_zeros));
return {first + precision, std::errc()};
if (precision - num_leading_zeros > 0)

Check warning on line 589 in include/boost/decimal/charconv.hpp

View check run for this annotation

Codecov / codecov/patch

include/boost/decimal/charconv.hpp#L589

Added line #L589 was not covered by tests
{
boost::decimal::detail::memset(first, '0', static_cast<std::size_t>(precision - num_leading_zeros));
return {first + precision, std::errc()};

Check warning on line 592 in include/boost/decimal/charconv.hpp

View check run for this annotation

Codecov / codecov/patch

include/boost/decimal/charconv.hpp#L591-L592

Added lines #L591 - L592 were not covered by tests
}
else
{
return {first, std::errc()};

Check warning on line 596 in include/boost/decimal/charconv.hpp

View check run for this annotation

Codecov / codecov/patch

include/boost/decimal/charconv.hpp#L596

Added line #L596 was not covered by tests
}
}
}
}
Expand Down
1 change: 1 addition & 0 deletions include/boost/decimal/detail/memcpy.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
1 change: 1 addition & 0 deletions test/Jamfile
Original file line number Diff line number Diff line change
Expand Up @@ -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 ;
Expand Down
27 changes: 27 additions & 0 deletions test/crash_report_1.cpp
Original file line number Diff line number Diff line change
@@ -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 <boost/decimal.hpp>
#include <boost/core/lightweight_test.hpp>
#include <iostream>

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();
}
35 changes: 34 additions & 1 deletion test/test_to_chars.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ static constexpr auto N = static_cast<std::size_t>(1024U >> 4U); // Number of tr
#if !defined(BOOST_DECIMAL_DISABLE_CLIB) && !(defined(__GNUC__) && __GNUC__ >= 13 && !defined(__aarch64__))

template <typename T>
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);
Expand All @@ -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 <typename T>
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 <typename T>
void test_value(T val, const char* result)
{
Expand Down Expand Up @@ -764,6 +774,25 @@ void test_777()
test_value(value3, "-2111000000", chars_format::fixed, 0);
}

template <typename T>
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<decimal32>();
Expand Down Expand Up @@ -874,6 +903,10 @@ int main()
test_777<decimal64_fast>();
test_777<decimal128_fast>();

test_more_powers_10<decimal32>();
test_more_powers_10<decimal64>();
test_more_powers_10<decimal128>();

return boost::report_errors();
}

Expand Down
Loading