From the 2026-07-03 comprehensive review.
The FileDialogTask worker lambda captures this and writes m_result/m_done on completion (src/ui/FileDialog.cpp:184-198). ~FileDialogTask detaches the thread if !m_done (include/entity/ui/FileDialog.hpp:56-60), freeing the object while the worker still holds this. When the user later closes the native dialog, the worker writes into freed heap.
ProjectLauncher::reset() dodges this deliberately, but ~ProjectLauncher → ~unique_ptr<FileDialogTask> → detach → UAF.
Trigger: quit the app (or destroy the launcher) with an Open/Browse dialog still open.
Fix: give the worker shared ownership of the result slot (shared_ptr state written under it) so destruction is safe, or signal cancellation and join with a bounded wait. Detach-with-captured-this is the bug pattern; any fix that removes the raw this capture works.
From the 2026-07-03 comprehensive review.
The FileDialogTask worker lambda captures
thisand writesm_result/m_doneon completion (src/ui/FileDialog.cpp:184-198).~FileDialogTaskdetaches the thread if!m_done(include/entity/ui/FileDialog.hpp:56-60), freeing the object while the worker still holdsthis. When the user later closes the native dialog, the worker writes into freed heap.ProjectLauncher::reset() dodges this deliberately, but
~ProjectLauncher→~unique_ptr<FileDialogTask>→ detach → UAF.Trigger: quit the app (or destroy the launcher) with an Open/Browse dialog still open.
Fix: give the worker shared ownership of the result slot (shared_ptr state written under it) so destruction is safe, or signal cancellation and join with a bounded wait. Detach-with-captured-this is the bug pattern; any fix that removes the raw
thiscapture works.