bpo-33015: Fix UB in pthread PyThread_start_new_thread (GH-6008) (GH-10822)
https://github.com/python/cpython/commit/03b1200dfd03061e9ad0bff8199967bd80b... commit: 03b1200dfd03061e9ad0bff8199967bd80b9b900 branch: 3.6 author: Victor Stinner <vstinner@redhat.com> committer: GitHub <noreply@github.com> date: 2018-11-30T17:04:46+01:00 summary: bpo-33015: Fix UB in pthread PyThread_start_new_thread (GH-6008) (GH-10822) 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) files: A Misc/NEWS.d/next/Build/2018-08-24-09-48-25.bpo-33015.s21y74.rst M Python/thread_pthread.h diff --git a/Misc/NEWS.d/next/Build/2018-08-24-09-48-25.bpo-33015.s21y74.rst b/Misc/NEWS.d/next/Build/2018-08-24-09-48-25.bpo-33015.s21y74.rst new file mode 100644 index 000000000000..8c5a0c91a46b --- /dev/null +++ b/Misc/NEWS.d/next/Build/2018-08-24-09-48-25.bpo-33015.s21y74.rst @@ -0,0 +1,3 @@ +Fix an undefined behaviour in the pthread implementation of +:c:func:`PyThread_start_new_thread`: add a function wrapper to always return +``NULL``. diff --git a/Python/thread_pthread.h b/Python/thread_pthread.h index 3607341eaa58..baea71f9c33e 100644 --- a/Python/thread_pthread.h +++ b/Python/thread_pthread.h @@ -183,6 +183,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; +} long PyThread_start_new_thread(void (*func)(void *), void *arg) @@ -218,21 +240,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 -1; + } + + 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 -1; + } pthread_detach(th);
participants (1)
-
Victor Stinner