From: Derek Lesho dlesho@codeweavers.com
Signed-off-by: Derek Lesho dlesho@codeweavers.com Signed-off-by: Nikolay Sivov nsivov@codeweavers.com ---
v2: fixes use after free for just released item, and uninitialized local variable.
dlls/mf/samplegrabber.c | 60 +++++++++++++++-------------------------- 1 file changed, 21 insertions(+), 39 deletions(-)
diff --git a/dlls/mf/samplegrabber.c b/dlls/mf/samplegrabber.c index 7d9fa78732a..adb4ded54ff 100644 --- a/dlls/mf/samplegrabber.c +++ b/dlls/mf/samplegrabber.c @@ -708,61 +708,43 @@ static HRESULT WINAPI sample_grabber_stream_timer_callback_GetParameters(IMFAsyn return E_NOTIMPL; }
-static struct scheduled_item *stream_get_next_item(struct sample_grabber *grabber) -{ - struct scheduled_item *item = NULL; - struct list *e; - - if ((e = list_head(&grabber->items))) - item = LIST_ENTRY(e, struct scheduled_item, entry); - - return item; -} - static HRESULT WINAPI sample_grabber_stream_timer_callback_Invoke(IMFAsyncCallback *iface, IMFAsyncResult *result) { struct sample_grabber *grabber = impl_from_IMFAsyncCallback(iface); - struct scheduled_item *item; - BOOL sample_delivered; + BOOL sample_reported = FALSE, sample_delivered = FALSE; + struct scheduled_item *item, *item2; HRESULT hr;
EnterCriticalSection(&grabber->cs);
- /* Report and schedule next. */ - if (!grabber->is_shut_down && (item = stream_get_next_item(grabber))) + if (!grabber->is_shut_down) { - while (item) + LIST_FOR_EACH_ENTRY_SAFE(item, item2, &grabber->items, struct scheduled_item, entry) { - switch (item->type) + if (item->type == ITEM_TYPE_MARKER) + { + sample_grabber_stream_report_marker(grabber, &item->u.marker.context, S_OK); + stream_release_pending_item(item); + } + else if (item->type == ITEM_TYPE_SAMPLE) { - case ITEM_TYPE_SAMPLE: + if (!sample_reported) + { if (FAILED(hr = sample_grabber_report_sample(grabber, item->u.sample, &sample_delivered))) WARN("Failed to report a sample, hr %#x.\n", hr); stream_release_pending_item(item); - - /* Schedule next sample, skipping markers. */ - LIST_FOR_EACH_ENTRY(item, &grabber->items, struct scheduled_item, entry) - { - if (item->type == ITEM_TYPE_SAMPLE) - { - if (FAILED(hr = stream_schedule_sample(grabber, item))) - WARN("Failed to schedule a sample, hr %#x.\n", hr); - break; - } - } - - if (sample_delivered) - sample_grabber_stream_request_sample(grabber); - - item = NULL; - break; - case ITEM_TYPE_MARKER: - sample_grabber_stream_report_marker(grabber, &item->u.marker.context, S_OK); - stream_release_pending_item(item); - item = stream_get_next_item(grabber); + sample_reported = TRUE; + } + else + { + if (FAILED(hr = stream_schedule_sample(grabber, item))) + WARN("Failed to schedule a sample, hr %#x.\n", hr); break; + } } } + if (sample_delivered) + sample_grabber_stream_request_sample(grabber); }
LeaveCriticalSection(&grabber->cs);
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/mf/samplegrabber.c | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-)
diff --git a/dlls/mf/samplegrabber.c b/dlls/mf/samplegrabber.c index adb4ded54ff..eb116d81edf 100644 --- a/dlls/mf/samplegrabber.c +++ b/dlls/mf/samplegrabber.c @@ -802,11 +802,20 @@ static ULONG WINAPI sample_grabber_sink_AddRef(IMFMediaSink *iface) return refcount; }
+static void sample_grabber_release_pending_items(struct sample_grabber *grabber) +{ + struct scheduled_item *item, *next_item; + + LIST_FOR_EACH_ENTRY_SAFE(item, next_item, &grabber->items, struct scheduled_item, entry) + { + stream_release_pending_item(item); + } +} + static ULONG WINAPI sample_grabber_sink_Release(IMFMediaSink *iface) { struct sample_grabber *grabber = impl_from_IMFMediaSink(iface); ULONG refcount = InterlockedDecrement(&grabber->refcount); - struct scheduled_item *item, *next_item;
TRACE("%p, refcount %u.\n", iface, refcount);
@@ -836,10 +845,7 @@ static ULONG WINAPI sample_grabber_sink_Release(IMFMediaSink *iface) } if (grabber->sample_attributes) IMFAttributes_Release(grabber->sample_attributes); - LIST_FOR_EACH_ENTRY_SAFE(item, next_item, &grabber->items, struct scheduled_item, entry) - { - stream_release_pending_item(item); - } + sample_grabber_release_pending_items(grabber); DeleteCriticalSection(&grabber->cs); heap_free(grabber); } @@ -1031,6 +1037,7 @@ static HRESULT WINAPI sample_grabber_sink_Shutdown(IMFMediaSink *iface)
EnterCriticalSection(&grabber->cs); grabber->is_shut_down = TRUE; + sample_grabber_release_pending_items(grabber); if (SUCCEEDED(hr = IMFSampleGrabberSinkCallback_OnShutdown(sample_grabber_get_callback(grabber)))) { sample_grabber_set_presentation_clock(grabber, NULL);
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/mf/samplegrabber.c | 37 +++++++++++++++++-------------------- 1 file changed, 17 insertions(+), 20 deletions(-)
diff --git a/dlls/mf/samplegrabber.c b/dlls/mf/samplegrabber.c index eb116d81edf..24d9163d195 100644 --- a/dlls/mf/samplegrabber.c +++ b/dlls/mf/samplegrabber.c @@ -717,35 +717,32 @@ static HRESULT WINAPI sample_grabber_stream_timer_callback_Invoke(IMFAsyncCallba
EnterCriticalSection(&grabber->cs);
- if (!grabber->is_shut_down) + LIST_FOR_EACH_ENTRY_SAFE(item, item2, &grabber->items, struct scheduled_item, entry) { - LIST_FOR_EACH_ENTRY_SAFE(item, item2, &grabber->items, struct scheduled_item, entry) + if (item->type == ITEM_TYPE_MARKER) + { + sample_grabber_stream_report_marker(grabber, &item->u.marker.context, S_OK); + stream_release_pending_item(item); + } + else if (item->type == ITEM_TYPE_SAMPLE) { - if (item->type == ITEM_TYPE_MARKER) + if (!sample_reported) { - sample_grabber_stream_report_marker(grabber, &item->u.marker.context, S_OK); + if (FAILED(hr = sample_grabber_report_sample(grabber, item->u.sample, &sample_delivered))) + WARN("Failed to report a sample, hr %#x.\n", hr); stream_release_pending_item(item); + sample_reported = TRUE; } - else if (item->type == ITEM_TYPE_SAMPLE) + else { - if (!sample_reported) - { - if (FAILED(hr = sample_grabber_report_sample(grabber, item->u.sample, &sample_delivered))) - WARN("Failed to report a sample, hr %#x.\n", hr); - stream_release_pending_item(item); - sample_reported = TRUE; - } - else - { - if (FAILED(hr = stream_schedule_sample(grabber, item))) - WARN("Failed to schedule a sample, hr %#x.\n", hr); - break; - } + if (FAILED(hr = stream_schedule_sample(grabber, item))) + WARN("Failed to schedule a sample, hr %#x.\n", hr); + break; } } - if (sample_delivered) - sample_grabber_stream_request_sample(grabber); } + if (sample_delivered) + sample_grabber_stream_request_sample(grabber);
LeaveCriticalSection(&grabber->cs);
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/mf/samplegrabber.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-)
diff --git a/dlls/mf/samplegrabber.c b/dlls/mf/samplegrabber.c index 24d9163d195..92330abc9fe 100644 --- a/dlls/mf/samplegrabber.c +++ b/dlls/mf/samplegrabber.c @@ -407,12 +407,11 @@ static HRESULT WINAPI sample_grabber_stream_ProcessSample(IMFStreamSink *iface, if (!sample) return S_OK;
- if (grabber->is_shut_down) - return MF_E_STREAMSINK_REMOVED; - EnterCriticalSection(&grabber->cs);
- if (grabber->state == SINK_STATE_RUNNING) + if (grabber->is_shut_down) + hr = MF_E_STREAMSINK_REMOVED; + else if (grabber->state == SINK_STATE_RUNNING) { hr = IMFSample_GetSampleTime(sample, &sampletime);
@@ -479,12 +478,11 @@ static HRESULT WINAPI sample_grabber_stream_PlaceMarker(IMFStreamSink *iface, MF
TRACE("%p, %d, %p, %p.\n", iface, marker_type, marker_value, context_value);
- if (grabber->is_shut_down) - return MF_E_STREAMSINK_REMOVED; - EnterCriticalSection(&grabber->cs);
- if (grabber->state == SINK_STATE_RUNNING) + if (grabber->is_shut_down) + hr = MF_E_STREAMSINK_REMOVED; + else if (grabber->state == SINK_STATE_RUNNING) hr = stream_place_marker(grabber, marker_type, context_value);
LeaveCriticalSection(&grabber->cs);