Handle empty strings in `SimpleAtof` after stripping whitespace Add an explicit check for an empty string after `StripAsciiWhitespace` in `SimpleAtof` to avoid issues with `absl::from_chars`, which does not accept empty input. PiperOrigin-RevId: 827589429 Change-Id: Iaf7e486d40d2c981a070aab912c7c61b72b33553
diff --git a/absl/strings/numbers.cc b/absl/strings/numbers.cc index 01caf78..60e43e0 100644 --- a/absl/strings/numbers.cc +++ b/absl/strings/numbers.cc
@@ -50,11 +50,15 @@ bool SimpleAtof(absl::string_view str, float* absl_nonnull out) { *out = 0.0; str = StripAsciiWhitespace(str); + if (str.empty()) { + // absl::from_chars doesn't accept empty strings. + return false; + } // std::from_chars doesn't accept an initial +, but SimpleAtof does, so if one // is present, skip it, while avoiding accepting "+-0" as valid. - if (!str.empty() && str[0] == '+') { + if (str[0] == '+') { str.remove_prefix(1); - if (!str.empty() && str[0] == '-') { + if (str.empty() || str[0] == '-') { return false; } }
diff --git a/absl/strings/numbers_test.cc b/absl/strings/numbers_test.cc index 1a82087..ca13da0 100644 --- a/absl/strings/numbers_test.cc +++ b/absl/strings/numbers_test.cc
@@ -451,6 +451,20 @@ VerifySimpleAtoiGood<std::string::size_type>(42, 42); } +TEST(NumbersTest, AtodEmpty) { + double d; + EXPECT_FALSE(absl::SimpleAtod("", &d)); + // Empty string_view takes a different code path from "". + EXPECT_FALSE(absl::SimpleAtod({}, &d)); +} + +TEST(NumbersTest, AtofEmpty) { + float f; + EXPECT_FALSE(absl::SimpleAtof("", &f)); + // Empty string_view takes a different code path from "". + EXPECT_FALSE(absl::SimpleAtof({}, &f)); +} + TEST(NumbersTest, Atod) { // DBL_TRUE_MIN and FLT_TRUE_MIN were not mandated in <cfloat> before C++17. #if !defined(DBL_TRUE_MIN)