VoiceInk icon indicating copy to clipboard operation
VoiceInk copied to clipboard

Crash - NSScreen.screens array accessed without bounds check

Open ebrindley opened this issue 1 month ago • 0 comments

Crash - NSScreen.screens array accessed without bounds check

Labels: bug, crash, low-priority

Description

NotificationManager accesses NSScreen.screens[0] as a fallback without checking if the array is empty, which crashes in headless mode or when all screens are disconnected.

User Impact

  • Crash if app runs in headless mode or when all screens disconnected

  • Edge case but can occur in server environments or during screen configuration changes

  • Affects users with unusual multi-monitor setups during transitions

Technical Details

File: VoiceInk/Notifications/NotificationManager.swift

Line: 83


let activeScreen = NSApp.keyWindow?.screen ?? NSScreen.main ?? NSScreen.screens[0]

The method is correctly marked @MainActor (line 81), so thread safety is not an issue. The problem is the array subscript on NSScreen.screens[0] which will crash if no screens are available.

Reproduction

  1. Run app in headless mode (no display connected)

  2. Trigger a notification

  3. Observe crash on array access

Recommended Fix

Replace line 83 in VoiceInk/Notifications/NotificationManager.swift:


let activeScreen: NSScreen

if let windowScreen = NSApp.keyWindow?.screen {

    activeScreen = windowScreen

} else if let mainScreen = NSScreen.main {

    activeScreen = mainScreen

} else if let firstScreen = NSScreen.screens.first {

    activeScreen = firstScreen

} else {

    // No screens available - cannot position notification

    return

}

Testing

  1. Test with multiple monitors

  2. Test connecting/disconnecting displays during app usage

  3. Verify notifications appear correctly in all scenarios

  4. Test in VM or headless environment if possible

ebrindley avatar Nov 12 '25 18:11 ebrindley