summaryrefslogtreecommitdiffstats
path: root/Python
diff options
context:
space:
mode:
authorMiss Islington (bot) <31488909+miss-islington@users.noreply.github.com>2023-02-22 19:11:59 (GMT)
committerGitHub <noreply@github.com>2023-02-22 19:11:59 (GMT)
commitddb65c47b1066fec8ce7a674ebb88b167f417d84 (patch)
tree1ac5d23e3064c02532f36441b960977a1f4c0924 /Python
parentedbde8feb7496e0f7898a49b80fb703c2d6012a8 (diff)
downloadcpython-ddb65c47b1066fec8ce7a674ebb88b167f417d84.zip
cpython-ddb65c47b1066fec8ce7a674ebb88b167f417d84.tar.gz
cpython-ddb65c47b1066fec8ce7a674ebb88b167f417d84.tar.bz2
[3.11] gh-97786: Fix compiler warnings in pytime.c (GH-101826) (#102062)
gh-97786: Fix compiler warnings in pytime.c (GH-101826) Fixes compiler warnings in pytime.c. (cherry picked from commit b1b375e2670a58fc37cb4c2629ed73b045159918) Co-authored-by: Mark Dickinson <dickinsm@gmail.com> Co-authored-by: Shantanu <12621235+hauntsaninja@users.noreply.github.com>
Diffstat (limited to 'Python')
-rw-r--r--Python/pytime.c35
1 files changed, 29 insertions, 6 deletions
diff --git a/Python/pytime.c b/Python/pytime.c
index f49a25b..f4f112f 100644
--- a/Python/pytime.c
+++ b/Python/pytime.c
@@ -1,5 +1,4 @@
#include "Python.h"
-#include "pycore_pymath.h" // _Py_InIntegralTypeRange()
#ifdef MS_WINDOWS
# include <winsock2.h> // struct timeval
#endif
@@ -41,6 +40,14 @@
# error "unsupported time_t size"
#endif
+#if PY_TIME_T_MAX + PY_TIME_T_MIN != -1
+# error "time_t is not a two's complement integer type"
+#endif
+
+#if _PyTime_MIN + _PyTime_MAX != -1
+# error "_PyTime_t is not a two's complement integer type"
+#endif
+
static void
pytime_time_t_overflow(void)
@@ -294,7 +301,21 @@ pytime_double_to_denominator(double d, time_t *sec, long *numerator,
}
assert(0.0 <= floatpart && floatpart < denominator);
- if (!_Py_InIntegralTypeRange(time_t, intpart)) {
+ /*
+ Conversion of an out-of-range value to time_t gives undefined behaviour
+ (C99 ยง6.3.1.4p1), so we must guard against it. However, checking that
+ `intpart` is in range is delicate: the obvious expression `intpart <=
+ PY_TIME_T_MAX` will first convert the value `PY_TIME_T_MAX` to a double,
+ potentially changing its value and leading to us failing to catch some
+ UB-inducing values. The code below works correctly under the mild
+ assumption that time_t is a two's complement integer type with no trap
+ representation, and that `PY_TIME_T_MIN` is within the representable
+ range of a C double.
+
+ Note: we want the `if` condition below to be true for NaNs; therefore,
+ resist any temptation to simplify by applying De Morgan's laws.
+ */
+ if (!((double)PY_TIME_T_MIN <= intpart && intpart < -(double)PY_TIME_T_MIN)) {
pytime_time_t_overflow();
return -1;
}
@@ -349,7 +370,8 @@ _PyTime_ObjectToTime_t(PyObject *obj, time_t *sec, _PyTime_round_t round)
d = pytime_round(d, round);
(void)modf(d, &intpart);
- if (!_Py_InIntegralTypeRange(time_t, intpart)) {
+ /* See comments in pytime_double_to_denominator */
+ if (!((double)PY_TIME_T_MIN <= intpart && intpart < -(double)PY_TIME_T_MIN)) {
pytime_time_t_overflow();
return -1;
}
@@ -507,8 +529,9 @@ pytime_from_double(_PyTime_t *tp, double value, _PyTime_round_t round,
d *= (double)unit_to_ns;
d = pytime_round(d, round);
- if (!_Py_InIntegralTypeRange(_PyTime_t, d)) {
- pytime_overflow();
+ /* See comments in pytime_double_to_denominator */
+ if (!((double)_PyTime_MIN <= d && d < -(double)_PyTime_MIN)) {
+ pytime_time_t_overflow();
return -1;
}
_PyTime_t ns = (_PyTime_t)d;
@@ -902,7 +925,7 @@ py_get_system_clock(_PyTime_t *tp, _Py_clock_info_t *info, int raise_exc)
info->monotonic = 0;
info->adjustable = 1;
if (clock_getres(CLOCK_REALTIME, &res) == 0) {
- info->resolution = res.tv_sec + res.tv_nsec * 1e-9;
+ info->resolution = (double)res.tv_sec + (double)res.tv_nsec * 1e-9;
}
else {
info->resolution = 1e-9;