Fatal error if timeout > PY_TIMEOUT_MAX · python/cpython@7c428b7 (original) (raw)

6 files changed

lines changed

Original file line number Diff line number Diff line change
@@ -787,6 +787,9 @@ extern _invalid_parameter_handler _Py_silent_invalid_parameter_handler;
787 787 #include <android/api-level.h>
788 788 #endif
789 789
790 +/* Maximum value of the Windows DWORD type */
791 +#define PY_DWORD_MAX 4294967295U
792 +
790 793 /* This macro used to tell whether Python was built with multithreading
791 794 * enabled. Now multithreading is always enabled, but keep the macro
792 795 * for compatibility.
Original file line number Diff line number Diff line change
@@ -42,21 +42,22 @@ PyAPI_FUNC(int) PyThread_acquire_lock(PyThread_type_lock, int);
42 42 and floating-point numbers allowed.
43 43 */
44 44 #define PY_TIMEOUT_T long long
45 +
45 46 #if defined(_POSIX_THREADS)
46 47 /* PyThread_acquire_lock_timed() uses _PyTime_FromNanoseconds(us * 1000),
47 48 convert microseconds to nanoseconds. */
48 49 # define PY_TIMEOUT_MAX (PY_LLONG_MAX / 1000)
50 +#elif defined (NT_THREADS)
51 +/* In the NT API, the timeout is a DWORD and is expressed in milliseconds */
52 +# if 0xFFFFFFFFLL * 1000 < PY_LLONG_MAX
53 +# define PY_TIMEOUT_MAX (0xFFFFFFFFLL * 1000)
54 +# else
55 +# define PY_TIMEOUT_MAX PY_LLONG_MAX
56 +# endif
49 57 #else
50 58 # define PY_TIMEOUT_MAX PY_LLONG_MAX
51 59 #endif
52 60
53 -/* In the NT API, the timeout is a DWORD and is expressed in milliseconds */
54 -#if defined (NT_THREADS)
55 -#if 0xFFFFFFFFLL * 1000 < PY_TIMEOUT_MAX
56 -#undef PY_TIMEOUT_MAX
57 -#define PY_TIMEOUT_MAX (0xFFFFFFFFLL * 1000)
58 -#endif
59 -#endif
60 61
61 62 /* If microseconds == 0, the call is non-blocking: it returns immediately
62 63 even when the lock can't be acquired.
Original file line number Diff line number Diff line change
@@ -61,8 +61,6 @@
61 61
62 62 #define T_HANDLE T_POINTER
63 63
64 -#define DWORD_MAX 4294967295U
65 -
66 64 /* Grab CancelIoEx dynamically from kernel32 */
67 65 static int has_CancelIoEx = -1;
68 66 static BOOL (CALLBACK *Py_CancelIoEx)(HANDLE, LPOVERLAPPED);
@@ -184,7 +182,7 @@ class DWORD_return_converter(CReturnConverter):
184 182
185 183 def render(self, function, data):
186 184 self.declare(data)
187 - self.err_occurred_if("_return_value == DWORD_MAX", data)
185 + self.err_occurred_if("_return_value == PY_DWORD_MAX", data)
188 186 data.return_conversion.append(
189 187 'return_value = Py_BuildValue("k", _return_value);\n')
190 188 [python start generated code]*/
@@ -1009,7 +1007,7 @@ _winapi_GetExitCodeProcess_impl(PyObject *module, HANDLE process)
1009 1007
1010 1008 if (! result) {
1011 1009 PyErr_SetFromWindowsErr(GetLastError());
1012 -exit_code = DWORD_MAX;
1010 +exit_code = PY_DWORD_MAX;
1013 1011 }
1014 1012
1015 1013 return exit_code;
@@ -1466,7 +1464,7 @@ _winapi_WriteFile_impl(PyObject *module, HANDLE handle, PyObject *buffer,
1466 1464 }
1467 1465
1468 1466 Py_BEGIN_ALLOW_THREADS
1469 -len = (DWORD)Py_MIN(buf->len, DWORD_MAX);
1467 +len = (DWORD)Py_MIN(buf->len, PY_DWORD_MAX);
1470 1468 ret = WriteFile(handle, buf->buf, len, &written,
1471 1469 overlapped ? &overlapped->overlapped : NULL);
1472 1470 Py_END_ALLOW_THREADS
Original file line number Diff line number Diff line change
@@ -390,8 +390,6 @@ static int win32_can_symlink = 0;
390 390 #endif
391 391 #endif
392 392
393 -#define DWORD_MAX 4294967295U
394 -
395 393 #ifdef MS_WINDOWS
396 394 #define INITFUNC PyInit_nt
397 395 #define MODNAME "nt"
@@ -3817,7 +3815,7 @@ os__getvolumepathname_impl(PyObject *module, PyObject *path)
3817 3815 /* Volume path should be shorter than entire path */
3818 3816 buflen = Py_MAX(buflen, MAX_PATH);
3819 3817
3820 -if (buflen > DWORD_MAX) {
3818 +if (buflen > PY_DWORD_MAX) {
3821 3819 PyErr_SetString(PyExc_OverflowError, "path too long");
3822 3820 return NULL;
3823 3821 }
Original file line number Diff line number Diff line change
@@ -283,12 +283,13 @@ PyThread_acquire_lock_timed(PyThread_type_lock aLock,
283 283 milliseconds = microseconds / 1000;
284 284 if (microseconds % 1000 > 0)
285 285 ++milliseconds;
286 -if ((DWORD) milliseconds != milliseconds)
287 -Py_FatalError("Timeout too large for a DWORD, "
288 - "please check PY_TIMEOUT_MAX");
286 +if (milliseconds > PY_DWORD_MAX) {
287 +Py_FatalError("Timeout larger than PY_TIMEOUT_MAX");
288 +}
289 289 }
290 -else
290 +else {
291 291 milliseconds = INFINITE;
292 + }
292 293
293 294 dprintf(("%lu: PyThread_acquire_lock_timed(%p, %lld) called\n",
294 295 PyThread_get_thread_ident(), aLock, microseconds));
Original file line number Diff line number Diff line change
@@ -324,13 +324,16 @@ PyThread_acquire_lock_timed(PyThread_type_lock lock, PY_TIMEOUT_T microseconds,
324 324 dprintf(("PyThread_acquire_lock_timed(%p, %lld, %d) called\n",
325 325 lock, microseconds, intr_flag));
326 326
327 +if (microseconds > PY_TIMEOUT_MAX) {
328 +Py_FatalError("Timeout larger than PY_TIMEOUT_MAX");
329 + }
330 +
327 331 if (microseconds > 0) {
328 332 MICROSECONDS_TO_TIMESPEC(microseconds, ts);
329 333
330 334 if (!intr_flag) {
331 -/* the caller must ensures that microseconds <= PY_TIMEOUT_MAX
332 - and so microseconds * 1000 cannot overflow. PY_TIMEOUT_MAX
333 - is defined to prevent this specific overflow. */
335 +/* cannot overflow thanks to (microseconds > PY_TIMEOUT_MAX)
336 + check done above */
334 337 _PyTime_t timeout = _PyTime_FromNanoseconds(microseconds * 1000);
335 338 deadline = _PyTime_GetMonotonicClock() + timeout;
336 339 }
@@ -363,8 +366,9 @@ PyThread_acquire_lock_timed(PyThread_type_lock lock, PY_TIMEOUT_T microseconds,
363 366 else if (dt > 0) {
364 367 _PyTime_t realtime_deadline = _PyTime_GetSystemClock() + dt;
365 368 if (_PyTime_AsTimespec(realtime_deadline, &ts) < 0) {
366 -success = PY_LOCK_FAILURE;
367 - goto exit;
369 +/* Cannot occur thanks to (microseconds > PY_TIMEOUT_MAX)
370 + check done above */
371 +Py_UNREACHABLE();
368 372 }
369 373 /* no need to update microseconds value, the code only care
370 374 if (microseconds > 0 or (microseconds == 0). */