Commit c84a46bb authored by Rémi Denis-Courmont's avatar Rémi Denis-Courmont

Win32: fix use-after-free in vlc_join() (untested)

parent 653a6637
...@@ -52,6 +52,7 @@ struct vlc_thread ...@@ -52,6 +52,7 @@ struct vlc_thread
HANDLE cancel_event; HANDLE cancel_event;
#endif #endif
bool detached;
bool killable; bool killable;
bool killed; bool killed;
vlc_cleanup_t *cleaners; vlc_cleanup_t *cleaners;
...@@ -152,7 +153,7 @@ BOOL WINAPI DllMain (HINSTANCE hinstDll, DWORD fdwReason, LPVOID lpvReserved) ...@@ -152,7 +153,7 @@ BOOL WINAPI DllMain (HINSTANCE hinstDll, DWORD fdwReason, LPVOID lpvReserved)
case DLL_PROCESS_ATTACH: case DLL_PROCESS_ATTACH:
vlc_mutex_init (&super_mutex); vlc_mutex_init (&super_mutex);
vlc_cond_init (&super_variable); vlc_cond_init (&super_variable);
vlc_threadvar_create (&thread_key, free); vlc_threadvar_create (&thread_key, NULL);
break; break;
case DLL_PROCESS_DETACH: case DLL_PROCESS_DETACH:
...@@ -551,6 +552,8 @@ static unsigned __stdcall vlc_entry (void *p) ...@@ -551,6 +552,8 @@ static unsigned __stdcall vlc_entry (void *p)
th->killable = true; th->killable = true;
th->entry (th->data); th->entry (th->data);
vlc_threadvar_cleanup (); vlc_threadvar_cleanup ();
if (th->detached)
free (th);
return 0; return 0;
} }
...@@ -562,6 +565,7 @@ int vlc_clone (vlc_thread_t *p_handle, void * (*entry) (void *), void *data, ...@@ -562,6 +565,7 @@ int vlc_clone (vlc_thread_t *p_handle, void * (*entry) (void *), void *data,
return ENOMEM; return ENOMEM;
th->entry = entry; th->entry = entry;
th->data = data; th->data = data;
th->detached = p_handle == NULL;
th->killable = false; /* not until vlc_entry() ! */ th->killable = false; /* not until vlc_entry() ! */
th->killed = false; th->killed = false;
th->cleaners = NULL; th->cleaners = NULL;
...@@ -582,6 +586,7 @@ int vlc_clone (vlc_thread_t *p_handle, void * (*entry) (void *), void *data, ...@@ -582,6 +586,7 @@ int vlc_clone (vlc_thread_t *p_handle, void * (*entry) (void *), void *data,
} }
#else #else
/* FIXME: cancel_event is useless and leaked in detached threads */
th->cancel_event = CreateEvent (NULL, FALSE, FALSE, NULL); th->cancel_event = CreateEvent (NULL, FALSE, FALSE, NULL);
if (th->cancel_event == NULL) if (th->cancel_event == NULL)
{ {
...@@ -602,12 +607,16 @@ int vlc_clone (vlc_thread_t *p_handle, void * (*entry) (void *), void *data, ...@@ -602,12 +607,16 @@ int vlc_clone (vlc_thread_t *p_handle, void * (*entry) (void *), void *data,
#endif #endif
th->id = hThread; th->id = hThread;
*p_handle = th;
ResumeThread (hThread); ResumeThread (hThread);
if (priority) if (priority)
SetThreadPriority (hThread, priority); SetThreadPriority (hThread, priority);
if (p_handle != NULL)
*p_handle = th;
else
CloseHandle (hThread);
return 0; return 0;
} }
...@@ -623,18 +632,12 @@ void vlc_join (vlc_thread_t th, void **result) ...@@ -623,18 +632,12 @@ void vlc_join (vlc_thread_t th, void **result)
#ifdef UNDER_CE #ifdef UNDER_CE
CloseHandle (th->cancel_event); CloseHandle (th->cancel_event);
#endif #endif
free (th);
} }
int vlc_clone_detach (void *(*entry) (void *), void *data, int priority) int vlc_clone_detach (void *(*entry) (void *), void *data, int priority)
{ {
vlc_thread_t th; return vlc_clone (NULL, entry, data, priority);
int ret = vlc_clone (&th, entry, data, priority);
if (ret)
return ret;
/* FIXME: handle->cancel_event leak UNDER_CE */
CloseHandle (th->id);
return 0;
} }
/*** Thread cancellation ***/ /*** Thread cancellation ***/
...@@ -688,6 +691,9 @@ void vlc_testcancel (void) ...@@ -688,6 +691,9 @@ void vlc_testcancel (void)
if (th->killable && th->killed) if (th->killable && th->killed)
{ {
/* Detached threads cannot be cancelled */
assert (!th->detached);
for (vlc_cleanup_t *p = th->cleaners; p != NULL; p = p->next) for (vlc_cleanup_t *p = th->cleaners; p != NULL; p = p->next)
p->proc (p->data); p->proc (p->data);
vlc_threadvar_cleanup (); vlc_threadvar_cleanup ();
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment