summaryrefslogtreecommitdiff
path: root/absl/time/internal/cctz/src/time_zone_format.cc
diff options
context:
space:
mode:
Diffstat (limited to 'absl/time/internal/cctz/src/time_zone_format.cc')
-rw-r--r--absl/time/internal/cctz/src/time_zone_format.cc22
1 files changed, 18 insertions, 4 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);