From c3dee50e5bee92564d6da23a4310c099218b4b56 Mon Sep 17 00:00:00 2001 From: King_DuckZ Date: Thu, 13 Apr 2017 19:21:25 +0100 Subject: [PATCH] Don't use pow and log10 directly because it causes an overflow. --- include/duckhandy/lexical_cast.hpp | 6 +++++- test/unit/lexical_cast_test.cpp | 5 +++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/include/duckhandy/lexical_cast.hpp b/include/duckhandy/lexical_cast.hpp index 3ad1877..0bcb5ff 100644 --- a/include/duckhandy/lexical_cast.hpp +++ b/include/duckhandy/lexical_cast.hpp @@ -166,11 +166,15 @@ namespace dhandy { template template std::size_t dec::count_digits_implem (T parValue, dhandy::bt::index_seq, dhandy::bt::index_seq) { + static_assert(sizeof...(Digits) == CHAR_BIT * sizeof(T) + 1, "Too many values for Digits"); typedef typename std::make_unsigned::type UT; static constexpr UT powers[] = { 0, static_cast(dhandy::implem::power<10, Powers + 1>::value)... }; - static constexpr std::size_t maxdigits[] = { count_digits_bt(static_cast(sprout::pow(2.0, Digits))) - (std::numeric_limits::is_signed ? 1 : 0)... }; + //the maxdigits table is [len(str(pow(2,b))) for b in range(0,MAX_BITS)] + static constexpr std::size_t maxdigits[] = { static_cast(static_cast(Digits) / sprout::log2(10.0)) + 1 ... }; + static_assert(maxdigits[sizeof(maxdigits) / sizeof(maxdigits[0]) - 1] <= std::numeric_limits::max(), "Last item in maxdigits overflows T"); const auto bits = sizeof(parValue) * CHAR_BIT - dhandy::implem::count_leading_zeroes(dhandy::implem::abs(parValue)); static_assert(std::is_same::value, "Unexpected type"); + assert(bits < sizeof(maxdigits) / sizeof(maxdigits[0])); return (dhandy::implem::abs(parValue) < powers[maxdigits[bits] - 1] ? maxdigits[bits] - 1 : maxdigits[bits]) + dhandy::implem::is_negative::check(parValue); } diff --git a/test/unit/lexical_cast_test.cpp b/test/unit/lexical_cast_test.cpp index 98dc0b6..bee3d1e 100644 --- a/test/unit/lexical_cast_test.cpp +++ b/test/unit/lexical_cast_test.cpp @@ -78,4 +78,9 @@ TEST_CASE ("Check string to int conversions", "[s2i][lexical_cast]") { } TEST_CASE ("Check int to string conversions", "[i2s][lexical_cast]") { + using std::string; + using dhandy::lexical_cast; + + CHECK(lexical_cast(1) == "1"); + CHECK(lexical_cast(static_cast(0xFFFF)) == "65535"); }