Fix a use-after-free when closing QElectroTech without saving

Closing QElectroTech with an edited project and choosing "Close without
saving" read freed memory. Destroying the project clears each folio's
undo stack, which signals the Projects panel to refresh that project.
The refresh reached GenericPanel::updateItem(), whose only statement was
QApplication::processEvents(). That ran the editor window's pending
deleteLater(), destroying the panel, and GenericPanel::addProject() then
carried on using it (genericpanel.cpp:142).

The call was added in 2013 (70b7cd7d1) to keep the window responsive
while the panel reloaded, when it also listed the whole element
collection. The collection has its own panel now; this one lists
projects, folios and title block templates. updateItem() is again what
its comment says it is: a hook that does nothing.

Found by the GUI fuzzer under AddressSanitizer. Reproduced 3/3 on master
51b122993 (open a project, move everything on a folio, Ctrl+Q, Close
without Saving: heap-use-after-free, exit 1); 0/3 with this change
(exit 0, no report), with the save prompt confirmed on screen.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
ispyisail
2026-10-02 16:15:51 +13:00
parent 51b1229935
commit 924b87447f
+7 -1
View File
@@ -696,7 +696,13 @@ QTreeWidgetItem *GenericPanel::updateItem(QTreeWidgetItem *qtwi,
bool freshly_created) {
Q_UNUSED(options);
Q_UNUSED(freshly_created);
QApplication::processEvents();
//No QApplication::processEvents() here. It dates from when this
//panel also listed the whole element collection, to keep the
//window alive while that reloaded; the collection has its own
//panel now. Running the event loop from inside the panel's own
//methods let a pending deleteLater() destroy the panel while
//addProject() was still using it: closing QElectroTech without
//saving an edited project read freed memory.
return(qtwi);
}