diff options
author | Siddhesh Poyarekar <siddhesh.poyarekar@gmail.com> | 2018-11-30 15:14:25 (GMT) |
---|---|---|
committer | Victor Stinner <vstinner@redhat.com> | 2018-11-30 15:14:25 (GMT) |
commit | 9eea6eaf23067880f4af3a130e3f67c9812e2f30 (patch) | |
tree | 00006cb82b79d809ee2698a944425511a01ef61b /Python/thread_pthread.h | |
parent | 1600f60414e620c4298c15dac803427d8f0a977c (diff) | |
download | cpython-9eea6eaf23067880f4af3a130e3f67c9812e2f30.zip cpython-9eea6eaf23067880f4af3a130e3f67c9812e2f30.tar.gz cpython-9eea6eaf23067880f4af3a130e3f67c9812e2f30.tar.bz2 |
bpo-33015: Fix UB in pthread PyThread_start_new_thread (GH-6008)
Fix an undefined behaviour in the pthread implementation of
PyThread_start_new_thread(): add a function wrapper to always return
NULL.
Add pythread_callback struct and pythread_wrapper() to thread_pthread.h.
Diffstat (limited to 'Python/thread_pthread.h')
-rw-r--r-- | Python/thread_pthread.h | 40 |
1 files changed, 36 insertions, 4 deletions
diff --git a/Python/thread_pthread.h b/Python/thread_pthread.h index 6da8b3a..09e53a1 100644 --- a/Python/thread_pthread.h +++ b/Python/thread_pthread.h @@ -152,6 +152,28 @@ PyThread__init_thread(void) * Thread support. */ +/* bpo-33015: pythread_callback struct and pythread_wrapper() cast + "void func(void *)" to "void* func(void *)": always return NULL. + + PyThread_start_new_thread() uses "void func(void *)" type, whereas + pthread_create() requires a void* return value. */ +typedef struct { + void (*func) (void *); + void *arg; +} pythread_callback; + +static void * +pythread_wrapper(void *arg) +{ + /* copy func and func_arg and free the temporary structure */ + pythread_callback *callback = arg; + void (*func)(void *) = callback->func; + void *func_arg = callback->arg; + PyMem_RawFree(arg); + + func(func_arg); + return NULL; +} unsigned long PyThread_start_new_thread(void (*func)(void *), void *arg) @@ -188,21 +210,31 @@ PyThread_start_new_thread(void (*func)(void *), void *arg) pthread_attr_setscope(&attrs, PTHREAD_SCOPE_SYSTEM); #endif + pythread_callback *callback = PyMem_RawMalloc(sizeof(pythread_callback)); + + if (callback == NULL) { + return PYTHREAD_INVALID_THREAD_ID; + } + + callback->func = func; + callback->arg = arg; + status = pthread_create(&th, #if defined(THREAD_STACK_SIZE) || defined(PTHREAD_SYSTEM_SCHED_SUPPORTED) &attrs, #else (pthread_attr_t*)NULL, #endif - (void* (*)(void *))func, - (void *)arg - ); + pythread_wrapper, callback); #if defined(THREAD_STACK_SIZE) || defined(PTHREAD_SYSTEM_SCHED_SUPPORTED) pthread_attr_destroy(&attrs); #endif - if (status != 0) + + if (status != 0) { + PyMem_RawFree(callback); return PYTHREAD_INVALID_THREAD_ID; + } pthread_detach(th); |