Skip to content

Keep changing the notes folder from crashing the notes list - #34

Merged
dangduc merged 1 commit into
masterfrom
fix/table-view-stale-row-count
Sep 12, 2026
Merged

dangduc merged 1 commit into
masterfrom
fix/table-view-stale-row-count

Conversation

@dangduc

@dangduc dangduc commented Sep 12, 2026

Copy link
Copy Markdown
Owner

Problem

Changing the notes folder in Preferences crashed the app with EXC_BAD_ACCESS at address 0x0.

#0  -[NotesTableView viewingLocation]                          NotesTableView.m:514
#1  -[AppController notationListMightChange:]                  AppController.m:1804
#2  -[NVBrowserSession refreshKeepingCurrentNote:]             NVBrowserSession.m:463
#3  -[AppController attachLibrary:finishingOldLibrary:]        AppController_MultipleWindows.m
#4  -[NVApplicationController setLibrary:finishingOldLibrary:] NVApplicationController.m:247
#5  -[AppController settingChangedForSelectorString:]          AppController.m:830

Cause

-viewingLocation bounded its lookup with the table's cached row count and then indexed the data source's backing array with it:

if (pivotRow < nRows) {                                  // nRows = [self numberOfRows]
    ... [(FastListDataSource*)[self dataSource] immutableObjects][pivotRow]

Changing the notes folder replaces the library under every open browser window. -attachLibrary:finishingOldLibrary: installs a fresh data source, and the refresh runs while the table's cached count still describes the previous library.

The NULL is legitimate rather than corruption: -[FastListDataSource fillArrayFromArray:] only allocates objects when count > oldArraySize, so a data source that has never held a row keeps it NULL and -immutableObjects returns that.

Measured in lldb at the crash:

Expression Value
[[self dataSource] immutableObjects] 0x0
[self numberOfRows] 1 (stale)
[[self dataSource] count] 0

So the guard passed on a stale count and dereferenced NULL[0].

This is why direction matters: switching to an empty folder is survivable, while switching back is when a never-populated data source meets a non-zero cached count.

Fix

Bound the lookup by the data source's own count, and skip it when the backing array is absent.

Testing

New suite Tests/Regression/library-switch/, registered in Tests/run-regression-tests.py (14 checks):

  • a data source that has never held a row reports zero rows and a NULL backing array
  • changing the notes folder installs a different library, and an empty folder opens as empty
  • switching back to the original folder restores its notes without crashing

Reverting the guard and rebuilding crashes the suite (exit 245, SIGSEGV) at the switch back, so the check cannot pass vacuously.

The stale-count window cannot be staged directly, because -setDataSource: invalidates the table's cached row count — I tried, and the synthetic precondition failed to hold. It opens only during a real library switch, so the suite drives the switch end to end through the setAliasDataForDefaultDirectory:sender: default that the Preferences "Other..." item writes.

Ran on macOS 13.7.8, Intel Development build. Independent of #33.

https://claude.ai/code/session_01W5dVNP811hKcLKUmJHD1FG

Changing the notes folder replaces the library under every open browser window.
-[NotesTableView viewingLocation] bounded its lookup with [self numberOfRows],
the table's cached row count, and then indexed the data source's backing array
with it. During the replacement the table holds a fresh data source while that
cached count still describes the previous library.

-[FastListDataSource fillArrayFromArray:] only allocates its backing array when
the new count exceeds the old one, so a data source that has never held a row
returns NULL from -immutableObjects. Indexing it crashed with EXC_BAD_ACCESS at
address 0x0. Measured at the crash: immutableObjects NULL, [self numberOfRows] 1,
[[self dataSource] count] 0.

Bound the lookup by the data source's own count and skip it when the backing
array is absent.

Claude-Session: https://claude.ai/code/session_01W5dVNP811hKcLKUmJHD1FG
@dangduc
dangduc merged commit 782b00a into master Sep 12, 2026
3 checks passed
@dangduc
dangduc deleted the fix/table-view-stale-row-count branch September 12, 2026 06:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant