Skip to content

Commit 83be0b7

Browse files
frederick-vs-jacassioneriCaseyCarter
authored
Avoid arithmetic overflow in the constructors of weekday (#5156)
Co-authored-by: Cassio Neri <[email protected]> Co-authored-by: Casey Carter <[email protected]>
1 parent ac971a3 commit 83be0b7

File tree

2 files changed

+8
-2
lines changed
  • stl/inc
  • tests/std/tests/P0355R7_calendars_and_time_zones_dates

2 files changed

+8
-2
lines changed

stl/inc/chrono

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -473,10 +473,12 @@ namespace chrono {
473473
private:
474474
unsigned char _Weekday;
475475

476-
// courtesy of Howard Hinnant
476+
// courtesy of Howard Hinnant (modified to avoid overflow)
477477
// https://howardhinnant.github.io/date_algorithms.html#weekday_from_days
478478
_NODISCARD static constexpr unsigned int _Weekday_from_days(int _Tp) noexcept {
479-
return static_cast<unsigned int>(_Tp >= -4 ? (_Tp + 4) % 7 : (_Tp + 5) % 7 + 6);
479+
_STL_INTERNAL_STATIC_ASSERT(~0u % 7u == 3u); // offset for `_Tp < 0` needs to change
480+
const auto _Before_modulo = static_cast<unsigned int>(_Tp) + (_Tp >= 0 ? 4u : 0u);
481+
return _Before_modulo % 7u; // separate expression for MSVC codegen, see GH-5153
480482
}
481483
};
482484

tests/std/tests/P0355R7_calendars_and_time_zones_dates/test.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -281,6 +281,10 @@ constexpr void weekday_test() {
281281
assert(Sunday - Monday == days{6});
282282
assert(Sunday - Tuesday == days{5});
283283
assert(Wednesday - Thursday == days{6});
284+
285+
// GH-5153 "<chrono>: integer overflow in weekday::weekday(sys_days::max())"
286+
assert(weekday{sys_days::max()} == weekday{sys_days::max() - days{7}});
287+
assert(weekday{local_days::max()} == weekday{local_days::max() - days{7}});
284288
}
285289

286290
constexpr void weekday_indexed_test() {

0 commit comments

Comments
 (0)