diff options
author | Abseil Team <absl-team@google.com> | 2020-05-07T17·42-0700 |
---|---|---|
committer | vslashg <gfalcon@google.com> | 2020-05-07T19·26-0400 |
commit | a35ef8a62ce7cded2f131ccbd2b5c4a81d622507 (patch) | |
tree | 2b4a4451d714d8ebee30db71f7a0ee8430e9789e /absl/strings/internal/str_format | |
parent | bd317cae3bc2630d1b12c5f1d77036e937d1d725 (diff) |
Export of internal Abseil changes
-- 034c30a00c64d93b9fcbc9d99a0a33801544d741 by Gennadiy Rozental <rogeeff@google.com>: Split private handle interfaces accessor into a separate target with private visibility. PiperOrigin-RevId: 310391488 -- 6f6ca869309b17900b90849e08488ce7f7b0193a by Derek Mauro <dmauro@google.com>: Remove __CLANG_SUPPORT_DYN_ANNOTATION__, which is a symbol defined by us to be true in all builds PiperOrigin-RevId: 310385325 -- ed5c1880c86973c000e826a3006b38e53ab3ed52 by Samuel Benzaquen <sbenza@google.com>: Add tests to exercise extreme width and precision, and fix the overflows from it. PiperOrigin-RevId: 310224957 GitOrigin-RevId: 034c30a00c64d93b9fcbc9d99a0a33801544d741 Change-Id: I6c89a3c89ae92fa617c696044148ce9a79bcdda8
Diffstat (limited to 'absl/strings/internal/str_format')
-rw-r--r-- | absl/strings/internal/str_format/convert_test.cc | 25 | ||||
-rw-r--r-- | absl/strings/internal/str_format/float_conversion.cc | 20 |
2 files changed, 37 insertions, 8 deletions
diff --git a/absl/strings/internal/str_format/convert_test.cc b/absl/strings/internal/str_format/convert_test.cc index dd167f76e68f..20c6229fcb37 100644 --- a/absl/strings/internal/str_format/convert_test.cc +++ b/absl/strings/internal/str_format/convert_test.cc @@ -704,6 +704,31 @@ TEST_F(FormatConvertTest, FloatRound) { "1837869002408041296803276054561138153076171875"); } +// We don't actually store the results. This is just to exercise the rest of the +// machinery. +struct NullSink { + friend void AbslFormatFlush(NullSink *sink, string_view str) {} +}; + +template <typename... T> +bool FormatWithNullSink(absl::string_view fmt, const T &... a) { + NullSink sink; + FormatArgImpl args[] = {FormatArgImpl(a)...}; + return FormatUntyped(&sink, UntypedFormatSpecImpl(fmt), absl::MakeSpan(args)); +} + +TEST_F(FormatConvertTest, ExtremeWidthPrecision) { + for (const char *fmt : {"f"}) { + for (double d : {1e-100, 1.0, 1e100}) { + constexpr int max = std::numeric_limits<int>::max(); + EXPECT_TRUE(FormatWithNullSink(std::string("%.*") + fmt, max, d)); + EXPECT_TRUE(FormatWithNullSink(std::string("%1.*") + fmt, max, d)); + EXPECT_TRUE(FormatWithNullSink(std::string("%*") + fmt, max, d)); + EXPECT_TRUE(FormatWithNullSink(std::string("%*.*") + fmt, max, max, d)); + } + } +} + TEST_F(FormatConvertTest, LongDouble) { #ifdef _MSC_VER // MSVC has a different rounding policy than us so we can't test our diff --git a/absl/strings/internal/str_format/float_conversion.cc b/absl/strings/internal/str_format/float_conversion.cc index cdccc86f551c..a761a5a5f9ce 100644 --- a/absl/strings/internal/str_format/float_conversion.cc +++ b/absl/strings/internal/str_format/float_conversion.cc @@ -440,8 +440,10 @@ struct Padding { int right_spaces; }; -Padding ExtraWidthToPadding(int total_size, const FormatState &state) { - int missing_chars = std::max(state.conv.width() - total_size, 0); +Padding ExtraWidthToPadding(size_t total_size, const FormatState &state) { + if (state.conv.width() < 0 || state.conv.width() <= total_size) + return {0, 0, 0}; + int missing_chars = state.conv.width() - total_size; if (state.conv.has_left_flag()) { return {0, 0, missing_chars}; } else if (state.conv.has_zero_flag()) { @@ -462,8 +464,8 @@ void FinalPrint(absl::string_view data, int trailing_zeros, } auto padding = - ExtraWidthToPadding((state.sign_char != '\0' ? 1 : 0) + - static_cast<int>(data.size()) + trailing_zeros, + ExtraWidthToPadding((state.sign_char != '\0' ? 1 : 0) + data.size() + + static_cast<size_t>(trailing_zeros), state); state.sink->Append(padding.left_spaces, ' '); @@ -536,8 +538,9 @@ void FormatFFast(Int v, int exp, const FormatState &state) { // worry about anything after the `.`. void FormatFPositiveExpSlow(uint128 v, int exp, const FormatState &state) { BinaryToDecimal::RunConversion(v, exp, [&](BinaryToDecimal btd) { - const int total_digits = - btd.TotalDigits() + (state.ShouldPrintDot() ? state.precision + 1 : 0); + const size_t total_digits = + btd.TotalDigits() + + (state.ShouldPrintDot() ? static_cast<size_t>(state.precision) + 1 : 0); const auto padding = ExtraWidthToPadding( total_digits + (state.sign_char != '\0' ? 1 : 0), state); @@ -562,8 +565,9 @@ void FormatFPositiveExpSlow(uint128 v, int exp, const FormatState &state) { // This one is guaranteed to be < 1.0, so we don't have to worry about integral // digits. void FormatFNegativeExpSlow(uint128 v, int exp, const FormatState &state) { - const int total_digits = - /* 0 */ 1 + (state.ShouldPrintDot() ? state.precision + 1 : 0); + const size_t total_digits = + /* 0 */ 1 + + (state.ShouldPrintDot() ? static_cast<size_t>(state.precision) + 1 : 0); auto padding = ExtraWidthToPadding(total_digits + (state.sign_char ? 1 : 0), state); padding.zeros += 1; |