summaryrefslogtreecommitdiff
path: root/absl/time/internal
diff options
context:
space:
mode:
Diffstat (limited to 'absl/time/internal')
-rw-r--r--absl/time/internal/cctz/src/time_zone_format.cc22
-rw-r--r--absl/time/internal/cctz/src/time_zone_format_test.cc5
-rw-r--r--absl/time/internal/cctz/src/time_zone_libc.cc9
-rw-r--r--absl/time/internal/cctz/src/tzfile.h8
4 files changed, 31 insertions, 13 deletions
diff --git a/absl/time/internal/cctz/src/time_zone_format.cc b/absl/time/internal/cctz/src/time_zone_format.cc
index 2e02233c..d8cb0474 100644
--- a/absl/time/internal/cctz/src/time_zone_format.cc
+++ b/absl/time/internal/cctz/src/time_zone_format.cc
@@ -654,14 +654,23 @@ const char* ParseTM(const char* dp, const char* fmt, std::tm* tm) {
}
// Sets year, tm_mon and tm_mday given the year, week_num, and tm_wday,
-// and the day on which weeks are defined to start.
-void FromWeek(int week_num, weekday week_start, year_t* year, std::tm* tm) {
+// and the day on which weeks are defined to start. Returns false if year
+// would need to move outside its bounds.
+bool FromWeek(int week_num, weekday week_start, year_t* year, std::tm* tm) {
const civil_year y(*year % 400);
civil_day cd = prev_weekday(y, week_start); // week 0
cd = next_weekday(cd - 1, FromTmWday(tm->tm_wday)) + (week_num * 7);
- *year += cd.year() - y.year();
+ if (const year_t shift = cd.year() - y.year()) {
+ if (shift > 0) {
+ if (*year > std::numeric_limits<year_t>::max() - shift) return false;
+ } else {
+ if (*year < std::numeric_limits<year_t>::min() - shift) return false;
+ }
+ *year += shift;
+ }
tm->tm_mon = cd.month() - 1;
tm->tm_mday = cd.day();
+ return true;
}
} // namespace
@@ -965,7 +974,12 @@ bool parse(const std::string& format, const std::string& input,
}
// Compute year, tm.tm_mon and tm.tm_mday if we parsed a week number.
- if (week_num != -1) FromWeek(week_num, week_start, &year, &tm);
+ if (week_num != -1) {
+ if (!FromWeek(week_num, week_start, &year, &tm)) {
+ if (err != nullptr) *err = "Out-of-range field";
+ return false;
+ }
+ }
const int month = tm.tm_mon + 1;
civil_second cs(year, month, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec);
diff --git a/absl/time/internal/cctz/src/time_zone_format_test.cc b/absl/time/internal/cctz/src/time_zone_format_test.cc
index e625a839..a11f93e2 100644
--- a/absl/time/internal/cctz/src/time_zone_format_test.cc
+++ b/absl/time/internal/cctz/src/time_zone_format_test.cc
@@ -1481,6 +1481,11 @@ TEST(Parse, WeekYearShift) {
EXPECT_EQ(exp, tp);
EXPECT_TRUE(parse("%Y-%W-%w", "2020-52-5", utc, &tp));
EXPECT_EQ(exp, tp);
+
+ // Slipping into the previous/following calendar years should fail when
+ // we're already at the extremes.
+ EXPECT_FALSE(parse("%Y-%U-%u", "-9223372036854775808-0-7", utc, &tp));
+ EXPECT_FALSE(parse("%Y-%U-%u", "9223372036854775807-53-7", utc, &tp));
}
TEST(Parse, MaxRange) {
diff --git a/absl/time/internal/cctz/src/time_zone_libc.cc b/absl/time/internal/cctz/src/time_zone_libc.cc
index 47cf84c6..3fcc75bd 100644
--- a/absl/time/internal/cctz/src/time_zone_libc.cc
+++ b/absl/time/internal/cctz/src/time_zone_libc.cc
@@ -223,11 +223,10 @@ time_zone::civil_lookup TimeZoneLibC::MakeTime(const civil_second& cs) const {
civil_second() + ToUnixSeconds(time_point<seconds>::min());
static const civil_second max_tp_cs =
civil_second() + ToUnixSeconds(time_point<seconds>::max());
- const time_point<seconds> tp =
- (cs < min_tp_cs)
- ? time_point<seconds>::min()
- : (cs > max_tp_cs) ? time_point<seconds>::max()
- : FromUnixSeconds(cs - civil_second());
+ const time_point<seconds> tp = (cs < min_tp_cs) ? time_point<seconds>::min()
+ : (cs > max_tp_cs)
+ ? time_point<seconds>::max()
+ : FromUnixSeconds(cs - civil_second());
return {time_zone::civil_lookup::UNIQUE, tp, tp, tp};
}
diff --git a/absl/time/internal/cctz/src/tzfile.h b/absl/time/internal/cctz/src/tzfile.h
index 269fa36c..659f84cf 100644
--- a/absl/time/internal/cctz/src/tzfile.h
+++ b/absl/time/internal/cctz/src/tzfile.h
@@ -108,15 +108,15 @@ struct tzhead {
#ifndef TZ_MAX_TYPES
/* This must be at least 17 for Europe/Samara and Europe/Vilnius. */
#define TZ_MAX_TYPES 256 /* Limited by what (unsigned char)'s can hold */
-#endif /* !defined TZ_MAX_TYPES */
+#endif /* !defined TZ_MAX_TYPES */
#ifndef TZ_MAX_CHARS
#define TZ_MAX_CHARS 50 /* Maximum number of abbreviation characters */
- /* (limited by what unsigned chars can hold) */
-#endif /* !defined TZ_MAX_CHARS */
+/* (limited by what unsigned chars can hold) */
+#endif /* !defined TZ_MAX_CHARS */
#ifndef TZ_MAX_LEAPS
#define TZ_MAX_LEAPS 50 /* Maximum number of leap second corrections */
-#endif /* !defined TZ_MAX_LEAPS */
+#endif /* !defined TZ_MAX_LEAPS */
#endif /* !defined TZFILE_H */