[Python-checkins] bpo-26669: Fix nan arg value error in pytime.c (#3085)

Victor Stinner webhook-mailer at python.org
Fri Sep 8 19:05:08 EDT 2017


https://github.com/python/cpython/commit/829dacce4fca60fc3c3367980e75e21dfcdbe6be
commit: 829dacce4fca60fc3c3367980e75e21dfcdbe6be
branch: master
author: Han Lee <hanlee.dev at gmail.com>
committer: Victor Stinner <victor.stinner at gmail.com>
date: 2017-09-08T16:05:05-07:00
summary:

bpo-26669: Fix nan arg value error in pytime.c (#3085)

* Fix #26669

* Modify NaN check function and error message

* Fix pytime.c when arg is nan

* fix whitespace

files:
M Lib/test/test_time.py
M Python/pytime.c

diff --git a/Lib/test/test_time.py b/Lib/test/test_time.py
index 42323b90ec6..b2aedc3be50 100644
--- a/Lib/test/test_time.py
+++ b/Lib/test/test_time.py
@@ -485,6 +485,10 @@ def test_localtime_failure(self):
         self.assertRaises(OSError, time.localtime, invalid_time_t)
         self.assertRaises(OSError, time.ctime, invalid_time_t)
 
+        # Issue #26669: check for localtime() failure
+        self.assertRaises(ValueError, time.localtime, float("nan"))
+        self.assertRaises(ValueError, time.ctime, float("nan"))
+
     def test_get_clock_info(self):
         clocks = ['clock', 'perf_counter', 'process_time', 'time']
         if hasattr(time, 'monotonic'):
@@ -819,6 +823,11 @@ def c_int_filter(secs):
                                 lambda secs: secs * SEC_TO_NS,
                                 value_filter=c_int_filter)
 
+        # test nan
+        for time_rnd, _ in ROUNDING_MODES:
+            with self.assertRaises(TypeError):
+                PyTime_FromSeconds(float('nan'))
+
     def test_FromSecondsObject(self):
         from _testcapi import PyTime_FromSecondsObject
 
@@ -830,6 +839,11 @@ def test_FromSecondsObject(self):
             PyTime_FromSecondsObject,
             lambda ns: self.decimal_round(ns * SEC_TO_NS))
 
+        # test nan
+        for time_rnd, _ in ROUNDING_MODES:
+            with self.assertRaises(ValueError):
+                PyTime_FromSecondsObject(float('nan'), time_rnd)
+
     def test_AsSecondsDouble(self):
         from _testcapi import PyTime_AsSecondsDouble
 
@@ -843,6 +857,11 @@ def float_converter(ns):
                                 float_converter,
                                 NS_TO_SEC)
 
+        # test nan
+        for time_rnd, _ in ROUNDING_MODES:
+            with self.assertRaises(TypeError):
+                PyTime_AsSecondsDouble(float('nan'))
+
     def create_decimal_converter(self, denominator):
         denom = decimal.Decimal(denominator)
 
@@ -948,6 +967,11 @@ def test_object_to_timeval(self):
                                   self.create_converter(SEC_TO_US),
                                   value_filter=self.time_t_filter)
 
+         # test nan
+        for time_rnd, _ in ROUNDING_MODES:
+            with self.assertRaises(ValueError):
+                pytime_object_to_timeval(float('nan'), time_rnd)
+
     def test_object_to_timespec(self):
         from _testcapi import pytime_object_to_timespec
 
@@ -959,6 +983,11 @@ def test_object_to_timespec(self):
                                   self.create_converter(SEC_TO_NS),
                                   value_filter=self.time_t_filter)
 
+        # test nan
+        for time_rnd, _ in ROUNDING_MODES:
+            with self.assertRaises(ValueError):
+                pytime_object_to_timespec(float('nan'), time_rnd)
+
 
 if __name__ == "__main__":
     unittest.main()
diff --git a/Python/pytime.c b/Python/pytime.c
index f3c913226ce..7edb534596e 100644
--- a/Python/pytime.c
+++ b/Python/pytime.c
@@ -133,6 +133,11 @@ _PyTime_ObjectToDenominator(PyObject *obj, time_t *sec, long *numerator,
 
     if (PyFloat_Check(obj)) {
         double d = PyFloat_AsDouble(obj);
+        if (Py_IS_NAN(d)) {
+            *numerator = 0;
+            PyErr_SetString(PyExc_ValueError, "Invalid value NaN (not a number)");
+            return -1;
+        }
         return _PyTime_DoubleToDenominator(d, sec, numerator,
                                            denominator, round);
     }
@@ -154,6 +159,11 @@ _PyTime_ObjectToTime_t(PyObject *obj, time_t *sec, _PyTime_round_t round)
         volatile double d;
 
         d = PyFloat_AsDouble(obj);
+        if (Py_IS_NAN(d)) {
+            PyErr_SetString(PyExc_ValueError, "Invalid value NaN (not a number)");
+            return -1;
+        }
+
         d = _PyTime_Round(d, round);
         (void)modf(d, &intpart);
 
@@ -301,6 +311,10 @@ _PyTime_FromObject(_PyTime_t *t, PyObject *obj, _PyTime_round_t round,
     if (PyFloat_Check(obj)) {
         double d;
         d = PyFloat_AsDouble(obj);
+        if (Py_IS_NAN(d)) {
+            PyErr_SetString(PyExc_ValueError, "Invalid value NaN (not a number)");
+            return -1;
+        }
         return _PyTime_FromFloatObject(t, d, round, unit_to_ns);
     }
     else {



More information about the Python-checkins mailing list