From 874d204b85d424f45d85b499b1de527cbe4ea200 Mon Sep 17 00:00:00 2001 From: jolavillette Date: Thu, 2 Jul 2026 20:08:38 +0200 Subject: [PATCH] fix(SharedFiles): stop SIGSEGV when toggling "Popular files" after a search Searching a keyword and then clicking "Popular files" crashed in QSortFilterProxyModel::parent() (via rowsAboutToBeRemoved). SFDSortFilterProxyModel::setUploadedOnly() called invalidateFilter(), which runs Qt's incremental filter_changed row-removal path over the currently-mapped tree. After a search the tree is fully expanded and carries live persistent proxy indexes; removing an interior directory node frees the child mapping structs those indexes still point at, and the removal bookkeeping then dereferences freed memory -> SIGSEGV. The plain-search path never crashed because it is always preceded by a full model reset; the "Popular files" toggle was the only path that re-filtered without one (deliberately, to avoid a slow re-crawl). Use invalidate() instead: it rebuilds the whole proxy mapping via the layoutAboutToBeChanged/layoutChanged protocol, which remaps persistent indexes safely and never emits rowsAboutToBeRemoved. It rebuilds only the proxy mapping (lazy, near-instant) and does not re-crawl the source model, so the performance the toggle path was protecting is preserved. Co-Authored-By: Claude Opus 4.8 (1M context) --- .../src/gui/FileTransfer/SharedFilesDialog.cpp | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/retroshare-gui/src/gui/FileTransfer/SharedFilesDialog.cpp b/retroshare-gui/src/gui/FileTransfer/SharedFilesDialog.cpp index a2317aedb..317054dc9 100644 --- a/retroshare-gui/src/gui/FileTransfer/SharedFilesDialog.cpp +++ b/retroshare-gui/src/gui/FileTransfer/SharedFilesDialog.cpp @@ -120,7 +120,19 @@ public: void setUploadedOnly(bool val) { if (m_uploadedOnly != val) { m_uploadedOnly = val; - invalidateFilter(); + // Use invalidate() rather than invalidateFilter(). invalidateFilter() + // triggers Qt's *incremental* row-removal path (filter_changed), which + // emits rowsAboutToBeRemoved while walking the currently-mapped tree. + // With an active text filter and an expanded tree there are live + // persistent proxy indexes, and removing an interior directory node + // frees child mapping structs those indexes still point to -> the + // removal bookkeeping then dereferences freed memory inside + // QSortFilterProxyModel::parent() and crashes (SIGSEGV). This is the + // "search a keyword, then click Popular files" crash. + // invalidate() rebuilds the whole proxy mapping via the layoutChanged + // protocol, which remaps persistent indexes safely, and it does NOT + // re-crawl the source model, so it stays near-instant. + invalidate(); } }