From ea9c0dd2c27884691f0a0af983fd41d4d818e93f Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Mon, 30 Mar 2015 02:51:13 +0200 Subject: [PATCH] Issue #22117: Fix usage of _PyTime_AsTimeval() Add _PyTime_AsTimeval_noraise() function. Call it when it's not possible (or not useful) to raise a Python exception on overflow. --- Include/pytime.h | 8 +++++++- Modules/_ssl.c | 4 +--- Modules/_testcapimodule.c | 5 +---- Modules/socketmodule.c | 8 ++------ Modules/timemodule.c | 5 +---- Python/pytime.c | 19 +++++++++++++++++-- 6 files changed, 29 insertions(+), 20 deletions(-) diff --git a/Include/pytime.h b/Include/pytime.h index b8727748a0f..f14e1fc6fde 100644 --- a/Include/pytime.h +++ b/Include/pytime.h @@ -94,11 +94,17 @@ PyAPI_FUNC(PyObject *) _PyTime_AsNanosecondsObject(_PyTime_t t); /* Convert a timestamp to a timeval structure (microsecond resolution). tv_usec is always positive. - Return -1 if the conversion overflowed, return 0 on success. */ + Raise an exception and return -1 if the conversion overflowed, + return 0 on success. */ PyAPI_FUNC(int) _PyTime_AsTimeval(_PyTime_t t, struct timeval *tv, _PyTime_round_t round); +/* Similar to _PyTime_AsTimeval(), but don't raise an exception on error. */ +PyAPI_FUNC(int) _PyTime_AsTimeval_noraise(_PyTime_t t, + struct timeval *tv, + _PyTime_round_t round); + #if defined(HAVE_CLOCK_GETTIME) || defined(HAVE_KQUEUE) /* Convert a timestamp to a timespec structure (nanosecond resolution). tv_nsec is always positive. diff --git a/Modules/_ssl.c b/Modules/_ssl.c index 54f5d140ed4..217c77c5933 100644 --- a/Modules/_ssl.c +++ b/Modules/_ssl.c @@ -1651,9 +1651,7 @@ check_socket_and_wait_for_timeout(PySocketSockObject *s, int writing) if (!_PyIsSelectable_fd(s->sock_fd)) return SOCKET_TOO_LARGE_FOR_SELECT; - /* conversion was already checked for overflow when - the timeout was set */ - (void)_PyTime_AsTimeval(s->sock_timeout, &tv, _PyTime_ROUND_UP); + _PyTime_AsTimeval_noraise(s->sock_timeout, &tv, _PyTime_ROUND_UP); FD_ZERO(&fds); FD_SET(s->sock_fd, &fds); diff --git a/Modules/_testcapimodule.c b/Modules/_testcapimodule.c index 9abb7ccd195..128ba094b2e 100644 --- a/Modules/_testcapimodule.c +++ b/Modules/_testcapimodule.c @@ -3427,11 +3427,8 @@ test_PyTime_AsTimeval(PyObject *self, PyObject *args) if (check_time_rounding(round) < 0) return NULL; t = _PyTime_FromNanoseconds(ns); - if (_PyTime_AsTimeval(t, &tv, round) < 0) { - PyErr_SetString(PyExc_OverflowError, - "timeout doesn't fit into C timeval"); + if (_PyTime_AsTimeval(t, &tv, round) < 0) return NULL; - } seconds = PyLong_FromLong((PY_LONG_LONG)tv.tv_sec); if (seconds == NULL) diff --git a/Modules/socketmodule.c b/Modules/socketmodule.c index 93dcd419481..513405e507a 100644 --- a/Modules/socketmodule.c +++ b/Modules/socketmodule.c @@ -641,9 +641,7 @@ internal_select_ex(PySocketSockObject *s, int writing, _PyTime_t interval) n = poll(&pollfd, 1, timeout_int); Py_END_ALLOW_THREADS; #else - /* conversion was already checked for overflow when - the timeout was set */ - (void)_PyTime_AsTimeval(interval, &tv, _PyTime_ROUND_UP); + _PyTime_AsTimeval_noraise(interval, &tv, _PyTime_ROUND_UP); FD_ZERO(&fds); FD_SET(s->sock_fd, &fds); @@ -2454,9 +2452,7 @@ internal_connect(PySocketSockObject *s, struct sockaddr *addr, int addrlen, struct timeval tv; int conv; - /* conversion was already checked for overflow when - the timeout was set */ - (void)_PyTime_AsTimeval(s->sock_timeout, &tv, _PyTime_ROUND_UP); + _PyTime_AsTimeval_noraise(s->sock_timeout, &tv, _PyTime_ROUND_UP); Py_BEGIN_ALLOW_THREADS FD_ZERO(&fds); diff --git a/Modules/timemodule.c b/Modules/timemodule.c index 99e83cc6dc0..3ed3fb31bdc 100644 --- a/Modules/timemodule.c +++ b/Modules/timemodule.c @@ -1405,11 +1405,8 @@ pysleep(_PyTime_t secs) do { #ifndef MS_WINDOWS - if (_PyTime_AsTimeval(secs, &timeout, _PyTime_ROUND_UP) < 0) { - PyErr_SetString(PyExc_OverflowError, - "delay doesn't fit into C timeval"); + if (_PyTime_AsTimeval(secs, &timeout, _PyTime_ROUND_UP) < 0) return -1; - } Py_BEGIN_ALLOW_THREADS err = select(0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &timeout); diff --git a/Python/pytime.c b/Python/pytime.c index 2bf6ba5cf28..a7eda869a07 100644 --- a/Python/pytime.c +++ b/Python/pytime.c @@ -311,8 +311,9 @@ _PyTime_AsMicroseconds(_PyTime_t t, _PyTime_round_t round) return _PyTime_Multiply(t, 1000 * 1000, round); } -int -_PyTime_AsTimeval(_PyTime_t t, struct timeval *tv, _PyTime_round_t round) +static int +_PyTime_AsTimeval_impl(_PyTime_t t, struct timeval *tv, _PyTime_round_t round, + int raise) { _PyTime_t secs, ns; int res = 0; @@ -357,9 +358,23 @@ _PyTime_AsTimeval(_PyTime_t t, struct timeval *tv, _PyTime_round_t round) tv->tv_sec += 1; } + if (res && raise) + _PyTime_overflow(); return res; } +int +_PyTime_AsTimeval(_PyTime_t t, struct timeval *tv, _PyTime_round_t round) +{ + return _PyTime_AsTimeval_impl(t, tv, round, 1); +} + +int +_PyTime_AsTimeval_noraise(_PyTime_t t, struct timeval *tv, _PyTime_round_t round) +{ + return _PyTime_AsTimeval_impl(t, tv, round, 0); +} + #if defined(HAVE_CLOCK_GETTIME) || defined(HAVE_KQUEUE) int _PyTime_AsTimespec(_PyTime_t t, struct timespec *ts)