jk-jeon / dragonbox

Reference implementation of Dragonbox in C++
Apache License 2.0
610 stars 41 forks source link

Sign conversion may change value in remove_trailing_zeros_traits (implicit conversions) #70

Open djallen89 opened 3 weeks ago

djallen89 commented 3 weeks ago

In include/dragonbox/dragonbox.h, in each of the remove_trailing_zeros_traits structs, on lines 2974 and 3012, the statement exponent += s; invokes a warning from gcc when -Wconversions and Wsign-conversion are enabled.

I think a reasonable fix is the following:

                assert(s < detail::stdr::numeric_limits<DecimalExponentType>::max());
                auto sAddend = static_cast<DecimalExponentType>(s);
                assert(detail::stdr::numeric_limits<DecimalExponentType>::max() - sAddend > exponent);
                exponent += sAddend;

The suggestion would be better imo if detail::stdr had its own analogue of std::remove_reference, so that decltype could be used properly on exponent.

If s + exponent is expected to be able to wrap, that invokes undefined behavior without the option -fwrapv. If it is intended to wrap, a modification to the algorithm involving an unsigned exponent representation with memcpy's back and forth may be required.

jk-jeon commented 3 weeks ago

Thanks for raising the issue! In short, overflow can't happen so there is no UB.

In your suggestion,

djallen89 commented 3 weeks ago

My apologies, I didn't do a more in depth analysis of the code before submitting the issue. Thanks for responding so quickly!

jk-jeon commented 3 weeks ago

Oh, don't get me wrong. My point was that I will investigate further and come up with a better solution if any. Thanks again!