public inbox for gcc-cvs@sourceware.org
help / color / mirror / Atom feed
* [gcc r14-5469] libstdc++: Fix UB in weekday::weekday(sys_days) and add test
@ 2023-11-14 22:46 Jonathan Wakely
0 siblings, 0 replies; only message in thread
From: Jonathan Wakely @ 2023-11-14 22:46 UTC (permalink / raw)
To: gcc-cvs, libstdc++-cvs
https://gcc.gnu.org/g:f6ce081d0ffb5f25d71eb2f30fcfdff7f20dba22
commit r14-5469-gf6ce081d0ffb5f25d71eb2f30fcfdff7f20dba22
Author: Cassio Neri <cassio.neri@gmail.com>
Date: Sun Nov 12 01:33:52 2023 +0000
libstdc++: Fix UB in weekday::weekday(sys_days) and add test
The following has undefined behaviour (signed overflow) [1]:
weekday max{sys_days{days{numeric_limits<days::rep>::max()}}};
The issue is in this line when __n is very large and __n + 4 overflows:
return weekday(__n >= -4 ? (__n + 4) % 7 : (__n + 5) % 7 + 6);
In addition to fixing this bug, the new implementation makes the compiler emit
shorter and branchless code for x86-64 and ARM [2].
[1] https://godbolt.org/z/1s5bv7KfT
[2] https://godbolt.org/z/zKsabzrhs
libstdc++-v3/ChangeLog:
* include/std/chrono (weekday::_S_from_days): Fix UB.
* testsuite/std/time/weekday/1.cc: Add test for overflow.
Diff:
---
libstdc++-v3/include/std/chrono | 11 +++++++++--
libstdc++-v3/testsuite/std/time/weekday/1.cc | 9 +++++++++
2 files changed, 18 insertions(+), 2 deletions(-)
diff --git a/libstdc++-v3/include/std/chrono b/libstdc++-v3/include/std/chrono
index 45e7d269e4b..bd21ec189a5 100644
--- a/libstdc++-v3/include/std/chrono
+++ b/libstdc++-v3/include/std/chrono
@@ -930,8 +930,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
static constexpr weekday
_S_from_days(const days& __d)
{
- auto __n = __d.count();
- return weekday(__n >= -4 ? (__n + 4) % 7 : (__n + 5) % 7 + 6);
+ using _Rep = days::rep;
+ using _URep = make_unsigned_t<_Rep>;
+ const auto __n = __d.count();
+ const auto __m = static_cast<_URep>(__n);
+
+ // 1970-01-01 (__n = 0, __m = 0 ) -> Thursday (4)
+ // 1969-31-12 (__n = -1, __m = _URep(-1)) -> Wednesday (3)
+ const auto __offset = __n >= 0 ? _URep(4) : 3 - _URep(-1) % 7 - 7;
+ return weekday((__m + __offset) % 7);
}
public:
diff --git a/libstdc++-v3/testsuite/std/time/weekday/1.cc b/libstdc++-v3/testsuite/std/time/weekday/1.cc
index 00278c8b01c..e89fca47d4b 100644
--- a/libstdc++-v3/testsuite/std/time/weekday/1.cc
+++ b/libstdc++-v3/testsuite/std/time/weekday/1.cc
@@ -20,6 +20,7 @@
// Class template day [time.cal.weekday]
#include <chrono>
+#include <limits>
constexpr void
constexpr_weekday()
@@ -37,6 +38,14 @@ constexpr_weekday()
static_assert(weekday{3}[2].weekday() == weekday{3});
static_assert(weekday{3}[last].weekday() == weekday{3});
+ // Test for UB (overflow).
+ {
+ using rep = days::rep;
+ using std::numeric_limits;
+ constexpr weekday max{sys_days{days{numeric_limits<rep>::max()}}};
+ constexpr weekday min{sys_days{days{numeric_limits<rep>::min()}}};
+ }
+
static_assert(weekday{sys_days{1900y/January/1}} == Monday);
static_assert(weekday{sys_days{1970y/January/1}} == Thursday);
static_assert(weekday{sys_days{2020y/August/21}} == Friday);
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2023-11-14 22:46 UTC | newest]
Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-11-14 22:46 [gcc r14-5469] libstdc++: Fix UB in weekday::weekday(sys_days) and add test Jonathan Wakely
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).