Module: wine
Branch: master
Commit: e4cdcb1ec9f4f561773646e8708e6da18dbe4f5c
URL: https://gitlab.winehq.org/wine/wine/-/commit/e4cdcb1ec9f4f561773646e8708e6d…
Author: Zhiyi Zhang <zzhang(a)codeweavers.com>
Date: Wed Sep 27 10:25:23 2023 +0800
mf: Avoid a double free of presentation clock timers.
In clock_change_state() when a clock is running, a timer is removed from clock->timers. The same
timer is then used to create an async result, which will eventually calls present_clock_timer_callback_Invoke()
and release the same timer. Check if the timer is still in clock->timers before releasing it.
---
dlls/mf/clock.c | 14 ++++++++++----
1 file changed, 10 insertions(+), 4 deletions(-)
diff --git a/dlls/mf/clock.c b/dlls/mf/clock.c
index aef4366c6d9..e6be05d2794 100644
--- a/dlls/mf/clock.c
+++ b/dlls/mf/clock.c
@@ -1108,13 +1108,19 @@ static HRESULT WINAPI present_clock_timer_callback_Invoke(IMFAsyncCallback *ifac
if (FAILED(hr = IMFAsyncResult_GetObject(result, &object)))
return hr;
- timer = impl_clock_timer_from_IUnknown(object);
-
EnterCriticalSection(&clock->cs);
- list_remove(&timer->entry);
- IUnknown_Release(&timer->IUnknown_iface);
+ LIST_FOR_EACH_ENTRY(timer, &clock->timers, struct clock_timer, entry)
+ {
+ if (&timer->IUnknown_iface == object)
+ {
+ list_remove(&timer->entry);
+ IUnknown_Release(&timer->IUnknown_iface);
+ break;
+ }
+ }
LeaveCriticalSection(&clock->cs);
+ timer = impl_clock_timer_from_IUnknown(object);
IMFAsyncCallback_Invoke(timer->callback, timer->result);
IUnknown_Release(object);