Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit ea9c0dd

Browse files
committed
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.
1 parent 160e819 commit ea9c0dd

6 files changed

Lines changed: 29 additions & 20 deletions

File tree

Include/pytime.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,11 +94,17 @@ PyAPI_FUNC(PyObject *) _PyTime_AsNanosecondsObject(_PyTime_t t);
9494

9595
/* Convert a timestamp to a timeval structure (microsecond resolution).
9696
tv_usec is always positive.
97-
Return -1 if the conversion overflowed, return 0 on success. */
97+
Raise an exception and return -1 if the conversion overflowed,
98+
return 0 on success. */
9899
PyAPI_FUNC(int) _PyTime_AsTimeval(_PyTime_t t,
99100
struct timeval *tv,
100101
_PyTime_round_t round);
101102

103+
/* Similar to _PyTime_AsTimeval(), but don't raise an exception on error. */
104+
PyAPI_FUNC(int) _PyTime_AsTimeval_noraise(_PyTime_t t,
105+
struct timeval *tv,
106+
_PyTime_round_t round);
107+
102108
#if defined(HAVE_CLOCK_GETTIME) || defined(HAVE_KQUEUE)
103109
/* Convert a timestamp to a timespec structure (nanosecond resolution).
104110
tv_nsec is always positive.

Modules/_ssl.c

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1651,9 +1651,7 @@ check_socket_and_wait_for_timeout(PySocketSockObject *s, int writing)
16511651
if (!_PyIsSelectable_fd(s->sock_fd))
16521652
return SOCKET_TOO_LARGE_FOR_SELECT;
16531653

1654-
/* conversion was already checked for overflow when
1655-
the timeout was set */
1656-
(void)_PyTime_AsTimeval(s->sock_timeout, &tv, _PyTime_ROUND_UP);
1654+
_PyTime_AsTimeval_noraise(s->sock_timeout, &tv, _PyTime_ROUND_UP);
16571655

16581656
FD_ZERO(&fds);
16591657
FD_SET(s->sock_fd, &fds);

Modules/_testcapimodule.c

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3427,11 +3427,8 @@ test_PyTime_AsTimeval(PyObject *self, PyObject *args)
34273427
if (check_time_rounding(round) < 0)
34283428
return NULL;
34293429
t = _PyTime_FromNanoseconds(ns);
3430-
if (_PyTime_AsTimeval(t, &tv, round) < 0) {
3431-
PyErr_SetString(PyExc_OverflowError,
3432-
"timeout doesn't fit into C timeval");
3430+
if (_PyTime_AsTimeval(t, &tv, round) < 0)
34333431
return NULL;
3434-
}
34353432

34363433
seconds = PyLong_FromLong((PY_LONG_LONG)tv.tv_sec);
34373434
if (seconds == NULL)

Modules/socketmodule.c

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -641,9 +641,7 @@ internal_select_ex(PySocketSockObject *s, int writing, _PyTime_t interval)
641641
n = poll(&pollfd, 1, timeout_int);
642642
Py_END_ALLOW_THREADS;
643643
#else
644-
/* conversion was already checked for overflow when
645-
the timeout was set */
646-
(void)_PyTime_AsTimeval(interval, &tv, _PyTime_ROUND_UP);
644+
_PyTime_AsTimeval_noraise(interval, &tv, _PyTime_ROUND_UP);
647645

648646
FD_ZERO(&fds);
649647
FD_SET(s->sock_fd, &fds);
@@ -2454,9 +2452,7 @@ internal_connect(PySocketSockObject *s, struct sockaddr *addr, int addrlen,
24542452
struct timeval tv;
24552453
int conv;
24562454

2457-
/* conversion was already checked for overflow when
2458-
the timeout was set */
2459-
(void)_PyTime_AsTimeval(s->sock_timeout, &tv, _PyTime_ROUND_UP);
2455+
_PyTime_AsTimeval_noraise(s->sock_timeout, &tv, _PyTime_ROUND_UP);
24602456

24612457
Py_BEGIN_ALLOW_THREADS
24622458
FD_ZERO(&fds);

Modules/timemodule.c

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1405,11 +1405,8 @@ pysleep(_PyTime_t secs)
14051405

14061406
do {
14071407
#ifndef MS_WINDOWS
1408-
if (_PyTime_AsTimeval(secs, &timeout, _PyTime_ROUND_UP) < 0) {
1409-
PyErr_SetString(PyExc_OverflowError,
1410-
"delay doesn't fit into C timeval");
1408+
if (_PyTime_AsTimeval(secs, &timeout, _PyTime_ROUND_UP) < 0)
14111409
return -1;
1412-
}
14131410

14141411
Py_BEGIN_ALLOW_THREADS
14151412
err = select(0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &timeout);

Python/pytime.c

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -311,8 +311,9 @@ _PyTime_AsMicroseconds(_PyTime_t t, _PyTime_round_t round)
311311
return _PyTime_Multiply(t, 1000 * 1000, round);
312312
}
313313

314-
int
315-
_PyTime_AsTimeval(_PyTime_t t, struct timeval *tv, _PyTime_round_t round)
314+
static int
315+
_PyTime_AsTimeval_impl(_PyTime_t t, struct timeval *tv, _PyTime_round_t round,
316+
int raise)
316317
{
317318
_PyTime_t secs, ns;
318319
int res = 0;
@@ -357,9 +358,23 @@ _PyTime_AsTimeval(_PyTime_t t, struct timeval *tv, _PyTime_round_t round)
357358
tv->tv_sec += 1;
358359
}
359360

361+
if (res && raise)
362+
_PyTime_overflow();
360363
return res;
361364
}
362365

366+
int
367+
_PyTime_AsTimeval(_PyTime_t t, struct timeval *tv, _PyTime_round_t round)
368+
{
369+
return _PyTime_AsTimeval_impl(t, tv, round, 1);
370+
}
371+
372+
int
373+
_PyTime_AsTimeval_noraise(_PyTime_t t, struct timeval *tv, _PyTime_round_t round)
374+
{
375+
return _PyTime_AsTimeval_impl(t, tv, round, 0);
376+
}
377+
363378
#if defined(HAVE_CLOCK_GETTIME) || defined(HAVE_KQUEUE)
364379
int
365380
_PyTime_AsTimespec(_PyTime_t t, struct timespec *ts)

0 commit comments

Comments
 (0)