Vector35 / Vector35/binaryninja-api

Searching symbols whilst analysis is ongoing causes the UI to freeze for extended periods of time

Open
#7,996 9 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

UI: Symbols
Dominant language
C++
Stars
1.3k
Forks
298
Avg merge
5d 5h
Merged PRs (30d)
19

Description

Version and Platform (required):

  • Binary Ninja Version: 5.3.9208-dev Ultimate (8b909a0c)
  • Edition: Ultimate
  • OS: macOS
  • OS Version: 26.3
  • CPU Architecture: M1

Bug Description:
I entered text in the symbols view search bar during ongoing analysis, for a Mach-O binary with a large number of symbols (at least 200,000 and automatic symbol sorting had also been disabled), and this resulted in the UI freezing multiple times for 10s of seconds at a time. I didn't even need to change the text for it to freeze multiple times with responsiveness in between freezes. I also don't have the case sensitive or regex settings selected. Either way it shouldn't freeze the UI like this.

I had a debugger attached at the time and this was the call stack:

_platform_memmove (@_platform_memmove:110)
match (@match:11165)
pcre2_match_16 (@pcre2_match_16:761)
safe_pcre2_match_16(pcre2_real_code_16 const*, unsigned short const*, long long, long long, int, pcre2_real_match_data_16*, pcre2_real_match_context_16*) (@safe_pcre2_match_16(pcre2_real_code_16 const*, unsigned short const*, long long, long long, int, pcre2_real_match_data_16*, pcre2_real_match_context_16*):18)
QRegularExpressionPrivate::doMatch(QRegularExpressionMatchPrivate*, long long, QRegularExpressionPrivate::CheckSubjectStringOption, QRegularExpressionMatchPrivate const*) const (@QRegularExpressionPrivate::doMatch(QRegularExpressionMatchPrivate*, long long, QRegularExpressionPrivate::CheckSubjectStringOption, QRegularExpressionMatchPrivate const*) const:104)
QRegularExpression::match(QString const&, long long, QRegularExpression::MatchType, QFlags<QRegularExpression::MatchOption>) const (@QRegularExpression::match(QString const&, long long, QRegularExpression::MatchType, QFlags<QRegularExpression::MatchOption>) const:47)
QtPrivate::contains(QStringView, QString const*, QRegularExpression const&, QRegularExpressionMatch*) (@QtPrivate::contains(QStringView, QString const*, QRegularExpression const&, QRegularExpressionMatch*):31)
QSortFilterProxyModel::filterAcceptsRow(int, QModelIndex const&) const (@QSortFilterProxyModel::filterAcceptsRow(int, QModelIndex const&) const:310)
___lldb_unnamed_symbol16199 (@___lldb_unnamed_symbol16199:108)
QSortFilterProxyModelPrivate::filterAcceptsRowInternal(int, QModelIndex const&) const (@QSortFilterProxyModelPrivate::filterAcceptsRowInternal(int, QModelIndex const&) const:14)
QSortFilterProxyModelPrivate::handle_filter_changed(QList<int>&, QList<int>&, QModelIndex const&, QSortFilterProxyModel::Direction) (@QSortFilterProxyModelPrivate::handle_filter_changed(QList<int>&, QList<int>&, QModelIndex const&, QSortFilterProxyModel::Direction):114)
QSortFilterProxyModelPrivate::filter_changed(QFlags<QSortFilterProxyModel::Direction>, QModelIndex const&) (@QSortFilterProxyModelPrivate::filter_changed(QFlags<QSortFilterProxyModel::Direction>, QModelIndex const&):61)
QSortFilterProxyModel::endFilterChange(QFlags<QSortFilterProxyModel::Direction>) (@QSortFilterProxyModel::endFilterChange(QFlags<QSortFilterProxyModel::Direction>):17)
___lldb_unnamed_symbol16404 (@___lldb_unnamed_symbol16404:42)
void doActivate<false>(QObject*, int, void**) (@void doActivate<false>(QObject*, int, void**):354)
QAbstractItemModel::layoutChanged(QList<QPersistentModelIndex> const&, QAbstractItemModel::LayoutChangeHint) (@QAbstractItemModel::layoutChanged(QList<QPersistentModelIndex> const&, QAbstractItemModel::LayoutChangeHint):19)
QSortFilterProxyModelPrivate::_q_sourceLayoutChanged(QList<QPersistentModelIndex> const&, QAbstractItemModel::LayoutChangeHint) (@QSortFilterProxyModelPrivate::_q_sourceLayoutChanged(QList<QPersistentModelIndex> const&, QAbstractItemModel::LayoutChangeHint):139)
void doActivate<false>(QObject*, int, void**) (@void doActivate<false>(QObject*, int, void**):354)
QAbstractItemModel::layoutChanged(QList<QPersistentModelIndex> const&, QAbstractItemModel::LayoutChangeHint) (@QAbstractItemModel::layoutChanged(QList<QPersistentModelIndex> const&, QAbstractItemModel::LayoutChangeHint):19)
___lldb_unnamed_symbol16400 (@___lldb_unnamed_symbol16400:411)
QObject::event(QEvent*) (@QObject::event(QEvent*):84)
QApplicationPrivate::notify_helper(QObject*, QEvent*) (@QApplicationPrivate::notify_helper(QObject*, QEvent*):87)
QApplication::notify(QObject*, QEvent*) (@QApplication::notify(QObject*, QEvent*):120)
QCoreApplicationPrivate::sendPostedEvents(QObject*, int, QThreadData*) (@QCoreApplicationPrivate::sendPostedEvents(QObject*, int, QThreadData*):160)
QCocoaEventDispatcherPrivate::processPostedEvents() (@QCocoaEventDispatcherPrivate::processPostedEvents():98)
QCocoaEventDispatcherPrivate::postedEventsSourceCallback(void*) (@QCocoaEventDispatcherPrivate::postedEventsSourceCallback(void*):132)
__CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ (@__CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__:10)
__CFRunLoopDoSource0 (@__CFRunLoopDoSource0:46)
__CFRunLoopDoSources0 (@__CFRunLoopDoSources0:61)
__CFRunLoopRun (@__CFRunLoopRun:208)
_CFRunLoopRunSpecificWithOptions (@_CFRunLoopRunSpecificWithOptions:136)
RunCurrentEventLoopInMode (@RunCurrentEventLoopInMode:82)
ReceiveNextEventCommon (@ReceiveNextEventCommon:125)
_BlockUntilNextEventMatchingListInMode (@_BlockUntilNextEventMatchingListInMode:15)
_DPSBlockUntilNextEventMatchingListInMode (@_DPSBlockUntilNextEventMatchingListInMode:62)
_DPSNextEvent (@_DPSNextEvent:150)
-[NSApplication(NSEventRouting) _nextEventMatchingEventMask:untilDate:inMode:dequeue:] (@-[NSApplication(NSEventRouting) _nextEventMatchingEventMask:untilDate:inMode:dequeue:]:175)
-[NSApplication(NSEventRouting) nextEventMatchingMask:untilDate:inMode:dequeue:] (@-[NSApplication(NSEventRouting) nextEventMatchingMask:untilDate:inMode:dequeue:]:21)
-[NSApplication run] (@-[NSApplication run]:95)
QCocoaEventDispatcher::processEvents(QFlags<QEventLoop::ProcessEventsFlag>) (@QCocoaEventDispatcher::processEvents(QFlags<QEventLoop::ProcessEventsFlag>):541)

Looks like its doing some slow regex filtering operations on the UI thread when the symbols view needs updating.

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the Symbols view search bar and the filtering path shown in the stack, especially QSortFilterProxyModel::filterAcceptsRow and the layout-change handling during analysis. Reproduce on macOS with a Mach-O binary containing at least 200,000 symbols while analysis is ongoing and search filtering is active. Done means the UI remains responsive during repeated filtering and symbol-view updates.

Written by the indexing model from the issue text.

Assessment

Tech stack
cpp
Domain
desktop
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
45/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.