From: Han Lee Date: Fri, 8 Sep 2017 23:05:05 +0000 (+0900) Subject: bpo-26669: Fix nan arg value error in pytime.c (#3085) X-Git-Tag: v3.7.0a1~91 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=829dacce4fca60fc3c3367980e75e21dfcdbe6be;p=python 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 --- diff --git a/Lib/test/test_time.py b/Lib/test/test_time.py index 42323b90ec..b2aedc3be5 100644 --- a/Lib/test/test_time.py +++ b/Lib/test/test_time.py @@ -485,6 +485,10 @@ class TimeTestCase(unittest.TestCase): 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 @@ class TestCPyTime(CPyTimeTestCase, unittest.TestCase): 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 @@ class TestCPyTime(CPyTimeTestCase, unittest.TestCase): 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 @@ class TestCPyTime(CPyTimeTestCase, unittest.TestCase): 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 @@ class TestOldPyTime(CPyTimeTestCase, unittest.TestCase): 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 @@ class TestOldPyTime(CPyTimeTestCase, unittest.TestCase): 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 f3c913226c..7edb534596 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 {