PR #2347: Clamp subsecond of infinite log timestamps in FormatBoundedFields

Imported from GitHub PR https://github.com/abseil/abseil-cpp/pull/2347

We could choose to forbid infinite timestamps by contract, but it is also
important that logging not crash since it is used for debugging.

For LLVM this does not pessimize log statements since value range propagation
results in improved code generation from knowledge of the range.

Merge a10575089e2147ae4b529eaf22612551cfcbcf99 into 761ddc54db31993f215a49d53326d6a879d4cfb7

Merging this change closes #2347

PiperOrigin-RevId: 1008280506
diff --git a/absl/log/internal/log_format.cc b/absl/log/internal/log_format.cc
index ac33021..66b4cdc 100644
--- a/absl/log/internal/log_format.cc
+++ b/absl/log/internal/log_format.cc
@@ -17,6 +17,7 @@
 
 #include <string.h>
 
+#include <algorithm>
 #include <cstddef>
 #include <cstdint>
 #include <limits>
@@ -125,7 +126,10 @@
                                        p);
   p += 2;
   *p++ = '.';
-  const int64_t usecs = absl::ToInt64Microseconds(ci.subsecond);
+  // `ci.subsecond` is +/-InfiniteDuration() for absl::InfiniteFuture() and
+  // absl::InfinitePast(), so clamp it to the range PutTwoDigits() can encode.
+  const int64_t usecs =
+      std::clamp<int64_t>(absl::ToInt64Microseconds(ci.subsecond), 0, 999999);
   absl::numbers_internal::PutTwoDigits(static_cast<uint32_t>(usecs / 10000), p);
   p += 2;
   absl::numbers_internal::PutTwoDigits(static_cast<uint32_t>(usecs / 100 % 100),
diff --git a/absl/log/log_entry_test.cc b/absl/log/log_entry_test.cc
index 4b3af4c..4c06d79 100644
--- a/absl/log/log_entry_test.cc
+++ b/absl/log/log_entry_test.cc
@@ -465,4 +465,20 @@
   EXPECT_THAT(entry.entry().text_message(), Eq("hello world"));
 }
 
+TEST(LogEntryTest, InfiniteTimestamp) {
+  const auto format_prefix = [](absl::Time timestamp) {
+    std::string str(1000, '\0');
+    absl::Span<char> buf(&str[0], str.size());
+    const size_t prefix_size = absl::log_internal::FormatLogPrefix(
+        absl::LogSeverity::kInfo, timestamp, 451, "foo.cc", 1234,
+        absl::log_internal::PrefixFormat::kNotRaw, buf);
+    str.resize(prefix_size);
+    return str;
+  };
+  EXPECT_THAT(format_prefix(absl::InfiniteFuture()),
+              StartsWith("I1231 23:59:59.999999     451 foo.cc:1234] "));
+  EXPECT_THAT(format_prefix(absl::InfinitePast()),
+              StartsWith("I0101 00:00:00.000000     451 foo.cc:1234] "));
+}
+
 }  // namespace