-
Notifications
You must be signed in to change notification settings - Fork 272
Closed
Description
When dispatching a fire_and_forget lambda through a DispatcherQueue, we get a use-after-free:
#include <DispatcherQueue.h>
#define __cpp_coroutines // temporary workaround to get coroutines working in C++20 mode
#include <winrt/base.h>
#include <winrt/Windows.Foundation.h>
#include <winrt/Windows.System.h>
#include <chrono>
#include <iostream>
#include <memory>
winrt::Windows::System::DispatcherQueueController CreateDispatcherController()
{
const DispatcherQueueOptions options = {
.dwSize = sizeof(options),
.threadType = DQTYPE_THREAD_CURRENT,
.apartmentType = DQTAT_COM_STA
};
winrt::com_ptr<ABI::Windows::System::IDispatcherQueueController> controller;
winrt::check_hresult(CreateDispatcherQueueController(options, controller.put()));
return { controller.detach(), winrt::take_ownership_from_abi };
}
int main()
{
auto controller = CreateDispatcherController();
auto veryimportant = std::make_unique<int>(1337);
controller.DispatcherQueue().TryEnqueue([stillveryimportant = std::move(veryimportant)]() -> winrt::fire_and_forget
{
using namespace std::chrono_literals;
co_await 1s;
// use-after-free here
std::cout << *stillveryimportant;
});
MSG msg;
while (GetMessage(&msg, nullptr, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}The lambda internal this is freed on the first coroutine suspension point, meaning accessing captured variables after this point will lead to undefined behavior and crashes.
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
No labels