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). */ |