Repository navigation
Description
Steps to reproduce
This is a Windows engine/embedder bug, so the repro is native (C++) rather than Dart.
The attached app.zip is an unmodified flutter create --platforms=windows project plus this in windows/runner/flutter_window.cpp (FlutterWindow::OnCreate(), right before return true;):
std::thread([engine = flutter_controller_->engine()] {
std::this_thread::sleep_for(std::chrono::milliseconds(10000));
engine->PostPlatformThreadTask([] {
// Never reached: the process dies inside (*cb)() before the task body runs.
std::fprintf(stderr, "[repro] task body ran\n");
});
}).detach();
flutter build windows --debug, then run build\windows\x64\runner\Debug\postplatformthreadtask_uaf.exe directly.
About ten seconds after the window appears, the process crashes with an access violation (exit code 0xC0000005 / -1073741819) while servicing the posted task — the task body ran line never prints (cdb capture in Logs; the delay is generous so flutter run can attach first — with a shorter delay flutter run may instead report "App failed to start" because the app dies before the tool attaches, which is the same crash).
Expected results
Per the API contract documented in flutter_windows.h:
// If the task is discarded without being executed (e.g. during engine
// shutdown), |on_cancel| is called on the platform thread so the caller can
// cleanup allocations. |on_cancel| can be nullptr if no cleanup is needed.on_cancel should only ever run if a task is discarded without executing — never at post time, and never on the posting thread. In the repro, the task body should run on valid memory.
Actual results
on_cancel(user_data)is invoked synchronously, on the posting thread, inside theFlutterDesktopEnginePostPlatformThreadTaskcall.- The task is still queued and executed. With any
on_cancelthat releasesuser_data— the documented cleanup contract, and exactly what the shippedcpp_client_wrapper'sFlutterEngine::PostPlatformThreadTaskpasses (delete user_data,cpp_client_wrapper/flutter_engine.cc) — the platform thread then invokescallbackon freed memory. Every task posted through the official wrapper is a use-after-free, including on current master. - If the engine shuts down before the task runs, the heap-side
Contextdestructor callson_cancela second time → double free.
Code sample
The complete repro project is attached as app.zip — an unmodified flutter create --platforms=windows app plus this addition in windows/runner/flutter_window.cpp (FlutterWindow::OnCreate()):
Addition to windows/runner/flutter_window.cpp
std::thread([engine = flutter_controller_->engine()] {
std::this_thread::sleep_for(std::chrono::milliseconds(10000));
engine->PostPlatformThreadTask([] {
// Never reached: the process dies inside (*cb)() before the task body runs.
std::fprintf(stderr, "[repro] task body ran\n");
});
}).detach();Screenshots or Video
(None)
Logs
Crash under cdb — Flutter 3.47.5 stable, debug build, Windows 11 x64
(c03bc.bf060): Access violation - code c0000005 (!!! second chance !!!)
postplatformthreadtask_uaf!std::_Func_class<void>::operator()+0x35:
00007ff7`315469a5 488b00 mov rax,qword ptr [rax] ds:feeefeee`feeefeee=????????????????
Child-SP RetAddr Call Site
0000002e`426ff5c0 00007ff7`31544187 postplatformthreadtask_uaf!std::_Func_class<void>::operator()+0x35 [functional @ 1057]
0000002e`426ff600 00007ff7`315441c6 postplatformthreadtask_uaf!<lambda_...>::operator()+0x47 [cpp_client_wrapper\flutter_engine.cc @ 134]
0000002e`426ff650 00007ffb`c1071ffe postplatformthreadtask_uaf!<lambda_...>::<lambda_invoker_cdecl>+0x16
(Inline Function) --------`-------- flutter_windows!std::_Func_class<void>::operator()+0x1a [functional @ 874]
0000002e`426ff680 00007ffb`c1073e33 flutter_windows!flutter::TaskRunner::ProcessTasks+0x11c [task_runner.cc @ 55]
0000002e`426ff710 00007ffb`c1073f3b flutter_windows!flutter::TaskRunnerWindow::ProcessTasks+0xa5 [task_runner_window.cc @ 181]
0000002e`426ff7b0 00007ffc`cf0452c6 flutter_windows!flutter::TaskRunnerWindow::HandleMessage+0x23 [task_runner_window.cc @ 226]
0000002e`426ff7e0 00007ffc`cf045d9d USER32!CallWindowProcW+0x6a6
0000002e`426ff940 00007ff7`3153eef5 USER32!IsWindowUnicode+0x20d
0000002e`426ff9c0 00007ff7`31619152 postplatformthreadtask_uaf!wWinMain+0x235 [main.cpp @ 38]
[...CRT startup frames omitted...]flutter_engine.cc @ 134 is the wrapper's callback thunk ((*cb)();), invoked from the engine's platform-thread task pump. The dereferenced pointer reads 0xFEEEFEEE, the Windows debug-heap free fill. We originally hit this in a production app (background native thread posting through FlutterEngine::PostPlatformThreadTask); its crash showed the same stack with the debug-CRT free fill 0xDDDDDDDDDDDDDDDD.
Flutter Doctor output
Doctor output
[√] Flutter (Channel stable, 3.47.5, on Microsoft Windows [Version 10.0.26300.9457], locale zh-CN)
• Flutter version 3.47.5 on channel stable at <sdk path>
• Upstream repository https://github.com/flutter/flutter.git
• Framework revision 6a19cca564 (2026-09-17 14:13:22 -0400)
• Engine revision af7e796e16
• Dart version 3.13.4
• DevTools version 2.60.0
[√] Windows Version (Windows 11 or higher, 26H2, 2009)
[√] Visual Studio - develop Windows apps (Visual Studio Community 2026 18.10.2)
• Visual Studio Community 2026 version 18.10.12217.157
• Windows 10 SDK version 10.0.28000.0
Activity
Gustl22 commentedon Sep 27, 2026
Funny I just wanted to make the same report, and you were 30 minutes earlier :D
here is my reproduction just for reference: https://github.com/Gustl22/flutter_issue_post_platform_thread_app
I also already have a fix I can provide.
puneetkukreja98 commentedon Sep 28, 2026
@snowflysky Thanks for the report and the reproduction sample!
I was able to reproduce the crash on Windows using the provided sample in debug mode (
flutter build windows --debug). Running the executable resulted in an crash.Screen-shot:
flutter doctor -v:
[Windows] Fix PostPlatformThreadTask cancelling tasks before they run (…
feat: Expose PostPlatformThreadTask and IsPlatformThread to PluginReg…
github-actions commentedon Oct 22, 2026
This thread has been automatically locked since there has not been any recent activity after it was closed. If you are still experiencing a similar issue, please open a new bug, including the output of
flutter doctor -vand a minimal reproduction of the issue.[Windows] Fix PostPlatformThreadTask cancelling tasks before they run (…