From: Yuxuan Shui <yshui@codeweavers.com> Otherwise WMReader may invoke the reader callback of the asf_reader as we are releasing the its resources, which the reader callback may use, resulting in use-after-frees. --- dlls/qasf/asfreader.c | 3 ++- dlls/qasf/tests/asfreader.c | 25 +++++++++++++++++++++++++ 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/dlls/qasf/asfreader.c b/dlls/qasf/asfreader.c index ec7a0310e0a..18e01e06acf 100644 --- a/dlls/qasf/asfreader.c +++ b/dlls/qasf/asfreader.c @@ -444,6 +444,8 @@ static void asf_reader_destroy(struct strmbase_filter *iface) struct asf_reader *filter = impl_from_strmbase_filter(iface); struct strmbase_source *source; + IWMReader_Release(filter->reader); + while (filter->stream_count--) { source = &filter->streams[filter->stream_count].source; @@ -454,7 +456,6 @@ static void asf_reader_destroy(struct strmbase_filter *iface) free(filter->file_name); IWMReaderCallback_Release(filter->callback); - IWMReader_Release(filter->reader); strmbase_filter_cleanup(&filter->filter); diff --git a/dlls/qasf/tests/asfreader.c b/dlls/qasf/tests/asfreader.c index 62a08f6b78c..700e4ab2354 100644 --- a/dlls/qasf/tests/asfreader.c +++ b/dlls/qasf/tests/asfreader.c @@ -638,6 +638,31 @@ static void test_filter_state(void) ref = IBaseFilter_Release(filter); ok(!ref, "Got ref %ld.\n", ref); + + /* What happens if we release a running asf reader? */ + filter = create_asf_reader(); + hr = IBaseFilter_QueryInterface(filter, &IID_IFileSourceFilter, (void **)&file_source); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + hr = IFileSourceFilter_Load(file_source, filename, NULL); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + IFileSourceFilter_Release(file_source); + + hr = CoCreateInstance(&CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, + &IID_IFilterGraph, (void **)&graph); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + hr = IFilterGraph_AddFilter(graph, filter, NULL); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + ref = IFilterGraph_Release(graph); + ok(!ref, "Got ref %ld.\n", ref); + + hr = IBaseFilter_Run(filter, GetTickCount() * 10000); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + hr = IBaseFilter_GetState(filter, 0, &state); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + ok(state == State_Running, "Got state %#x.\n", state); + + ref = IBaseFilter_Release(filter); + ok(!ref, "Got ref %ld.\n", ref); } struct test_sink -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/9871