diff options
author | Miss Islington (bot) <31488909+miss-islington@users.noreply.github.com> | 2018-11-30 07:32:12 -0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-11-30 07:32:12 -0800 |
commit | b1355352d14a0a67107aba7ec6f233336f17716a (patch) | |
tree | c34317cf7a903b640fc1ef3b36612f28a1e91f79 /Python | |
parent | 365f21c2d3756a6768c5b0d479aaf5c2a568b80b (diff) | |
download | cpython-git-b1355352d14a0a67107aba7ec6f233336f17716a.tar.gz |
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.
(cherry picked from commit 9eea6eaf23067880f4af3a130e3f67c9812e2f30)
Co-authored-by: Siddhesh Poyarekar <siddhesh.poyarekar@gmail.com>
Diffstat (limited to 'Python')
-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 697140558f..f79f9b90a6 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); |