PR #2183: fix year overflow on leap-second carry in ParseCivilTime

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

ParseCivilTime parses the year on its own, normalises it into a small range around 2400 so the rest of the string can go through ParseTime, then rebuilds the result by adding the field-normalisation carry back onto the original year. The carry itself is small, but the year it is added to comes straight from the input, and at the largest representable year a trailing leap second rolls the value one past the maximum, so the addition overflows civil_year_t. It is reachable from untrusted text because the civil-time types parse flag and configuration strings through this path, and a value like 9223372036854775807-12-31T23:59:60 triggers it: a sanitiser build reports signed integer overflow at the carry, while an ordinary build silently wraps the year to the minimum and still returns success. I came across it while reading the carry handling that was added recently. Bounding the addition against the type limits and failing the parse when it would overflow leaves every normal year untouched and only rejects the few values that cannot be represented. I have added a regression case beside the existing carry test.
Merge d9ba674d286e8bdd4614956842e1a30b00a0763b into 511e3f4b7ee50848e52dad3b054887e19def5ad8

Merging this change closes #2183

PiperOrigin-RevId: 999343915
Change-Id: Ic18834bda53fae4aa21e1f17de5fbeac3eb95ae0
diff --git a/absl/time/civil_time.cc b/absl/time/civil_time.cc
index a704247..76dbcaf 100644
--- a/absl/time/civil_time.cc
+++ b/absl/time/civil_time.cc
@@ -16,6 +16,7 @@
 
 #include <cerrno>
 #include <cstdlib>
+#include <limits>
 #include <ostream>
 #include <string>
 
@@ -68,7 +69,15 @@
     // end-of-year rollover) can carry into the year. The other fields are taken
     // from `cs`, so the same carry must be applied to the original year;
     // otherwise the reconstructed value would use the wrong (un-carried) year.
-    const civil_year_t year = y + (cs.year() - normalized_year);
+    // `cs.year()` and `normalized_year` both lie in the normalized range, so
+    // the carry is small, but applying it to `y` can overflow civil_year_t when
+    // `y` is at the extreme representable year; reject that rather than wrap.
+    const civil_year_t carry = cs.year() - normalized_year;
+    if ((carry > 0 && y > (std::numeric_limits<civil_year_t>::max)() - carry) ||
+        (carry < 0 && y < (std::numeric_limits<civil_year_t>::min)() - carry)) {
+      return false;
+    }
+    const civil_year_t year = y + carry;
     *c =
         CivilT(year, cs.month(), cs.day(), cs.hour(), cs.minute(), cs.second());
     return true;
diff --git a/absl/time/civil_time_test.cc b/absl/time/civil_time_test.cc
index 3f03fc1..53f52a5 100644
--- a/absl/time/civil_time_test.cc
+++ b/absl/time/civil_time_test.cc
@@ -873,6 +873,19 @@
   EXPECT_EQ(absl::CivilSecond(0, 1, 1, 0, 0, 0), ss);
 }
 
+TEST(CivilTime, ParseYearCarryDoesNotOverflow) {
+  // A ":60" leap second on the last second of the maximum representable year
+  // carries into the year, which would be civil_year_t(max) + 1 and is not
+  // representable, so the parse must fail cleanly rather than overflow.
+  absl::CivilSecond ss;
+  EXPECT_FALSE(absl::ParseCivilTime("9223372036854775807-12-31T23:59:60", &ss))
+      << ss;
+  // The same year without a carry remains valid and round-trips.
+  EXPECT_TRUE(absl::ParseCivilTime("9223372036854775807-12-31T23:59:59", &ss))
+      << ss;
+  EXPECT_EQ("9223372036854775807-12-31T23:59:59", absl::FormatCivilTime(ss));
+}
+
 TEST(CivilTime, AbslStringify) {
   static_assert(absl::HasAbslStringify<absl::CivilSecond>::value);
   static_assert(absl::HasAbslStringify<absl::CivilMinute>::value);