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) <noreply@anthropic.com>
This commit is contained in:
jolavillette 2026-07-02 20:08:38 +02:00
parent d20c783769
commit 874d204b85

View File

@ -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();
}
}