From 7585b411957f73f6bda910b02e22d4483b5c4676 Mon Sep 17 00:00:00 2001 From: Alvaro-Kothe Date: Fri, 30 Jan 2026 15:08:52 -0300 Subject: [PATCH] fix: don't fail on overflow --- cpp/src/arrow/util/value_parsing.cc | 15 ++++++++++++--- cpp/src/arrow/util/value_parsing_test.cc | 12 ++++++++++++ 2 files changed, 24 insertions(+), 3 deletions(-) diff --git a/cpp/src/arrow/util/value_parsing.cc b/cpp/src/arrow/util/value_parsing.cc index 1a8e8066d703..0cc71f276df4 100644 --- a/cpp/src/arrow/util/value_parsing.cc +++ b/cpp/src/arrow/util/value_parsing.cc @@ -35,7 +35,10 @@ bool StringToFloat(const char* s, size_t length, char decimal_point, float* out) ::arrow_vendored::fast_float::chars_format::general, decimal_point}; const auto res = ::arrow_vendored::fast_float::from_chars_advanced(s, s + length, *out, options); - return res.ec == std::errc() && res.ptr == s + length; + const bool is_valid_number = + res.ec == std::errc() || res.ec == std::errc::result_out_of_range; + const bool consumed_entire_string = res.ptr == s + length; + return is_valid_number && consumed_entire_string; } bool StringToFloat(const char* s, size_t length, char decimal_point, double* out) { @@ -43,7 +46,10 @@ bool StringToFloat(const char* s, size_t length, char decimal_point, double* out ::arrow_vendored::fast_float::chars_format::general, decimal_point}; const auto res = ::arrow_vendored::fast_float::from_chars_advanced(s, s + length, *out, options); - return res.ec == std::errc() && res.ptr == s + length; + const bool is_valid_number = + res.ec == std::errc() || res.ec == std::errc::result_out_of_range; + const bool consumed_entire_string = res.ptr == s + length; + return is_valid_number && consumed_entire_string; } // Half float @@ -53,7 +59,10 @@ bool StringToFloat(const char* s, size_t length, char decimal_point, Float16* ou float temp_out; const auto res = ::arrow_vendored::fast_float::from_chars_advanced(s, s + length, temp_out, options); - const bool ok = res.ec == std::errc() && res.ptr == s + length; + const bool is_valid_number = + res.ec == std::errc() || res.ec == std::errc::result_out_of_range; + const bool consumed_entire_string = res.ptr == s + length; + const bool ok = is_valid_number && consumed_entire_string; if (ok) { *out = Float16::FromFloat(temp_out); } diff --git a/cpp/src/arrow/util/value_parsing_test.cc b/cpp/src/arrow/util/value_parsing_test.cc index b9e3b18444fa..b61f777685b7 100644 --- a/cpp/src/arrow/util/value_parsing_test.cc +++ b/cpp/src/arrow/util/value_parsing_test.cc @@ -141,6 +141,10 @@ TEST(StringConversion, ToFloat) { AssertConversion("0", 0.0f); AssertConversion("-0.0", -0.0f); AssertConversion("-1e20", -1e20f); + AssertConversion("4e38", std::numeric_limits::infinity()); + AssertConversion("-4e38", -std::numeric_limits::infinity()); + AssertConversion("1e-46", 0.0f); + AssertConversion("-1e-46", -0.0f); AssertConversion("+Infinity", std::numeric_limits::infinity()); AssertConversion("-Infinity", -std::numeric_limits::infinity()); AssertConversion("Infinity", std::numeric_limits::infinity()); @@ -166,6 +170,10 @@ TEST(StringConversion, ToDouble) { AssertConversion("0", 0); AssertConversion("-0.0", -0.0); AssertConversion("-1e100", -1e100); + AssertConversion("2e308", std::numeric_limits::infinity()); + AssertConversion("-2e308", -std::numeric_limits::infinity()); + AssertConversion("1e-325", 0.0); + AssertConversion("-1e-325", -0.0); AssertConversion("+Infinity", std::numeric_limits::infinity()); AssertConversion("-Infinity", -std::numeric_limits::infinity()); AssertConversion("Infinity", std::numeric_limits::infinity()); @@ -185,6 +193,10 @@ TEST(StringConversion, ToHalfFloat) { AssertConversion("0", Float16(0.0f)); AssertConversion("-0.0", Float16(-0.0f)); AssertConversion("-1e15", Float16(-1e15)); + AssertConversion("7e4", Float16::FromBits(0x7c00)); + AssertConversion("-7e4", Float16::FromBits(0xfc00)); + AssertConversion("1e-9", Float16(0.0f)); + AssertConversion("-1e-9", Float16(-0.0f)); AssertConversion("+Infinity", Float16::FromBits(0x7c00)); AssertConversion("-Infinity", Float16::FromBits(0xfc00)); AssertConversion("Infinity", Float16::FromBits(0x7c00));