Skip to content

sqlite3_finalize crash (EXC_BAD_ACCESS / SIGABRT double-free) on macOS with createBackgroundConnection #3771

@dbebawy

Description

@dbebawy

Describe the bug

Our Flutter app crashes on macOS with native sqlite3 memory errors during normal database usage via NativeDatabase.createBackgroundConnection(). We've observed two distinct crash signatures, both on the DartWorker thread (the background isolate), both involving sqlite3_finalize:

  1. EXC_BAD_ACCESS (KERN_INVALID_ADDRESS) in sqlite3_finalize
  2. SIGABRT in sqlite3VdbeDelete"pointer being freed was not allocated" (double-free)

Both crashes occur during normal read-heavy usage (scrolling through paginated content that triggers many sequential database queries). The app does NOT use multiple database instances or share the connection across isolates.

Environment

Component Version
drift 2.32.0
sqlite3 3.2.0
Flutter 3.38.x
Dart 3.10.x
sqlite3_flutter_libs Not used (system SQLite on macOS)

Affected platforms:

  • macOS 26.3.1 (Sequoia) on Apple M2 ARM64
  • macOS 12.7.6 (Monterey) on Intel x86_64

Not observed on iOS, Android, or other platforms.

Database connection setup

DatabaseConnection connect() {
  return DatabaseConnection.delayed(
    Future(() async {
      if (Platform.isAndroid) {
        sqlite3.tempDirectory = (await getTemporaryDirectory()).path;
      }
      final dbFile = await databaseFile;
      return NativeDatabase.createBackgroundConnection(dbFile);
    }),
  );
}

Single database instance, no shareAcrossIsolates, no custom setup callback, no readPool. Default configuration.

Crash 1: sqlite3_finalize EXC_BAD_ACCESS

  • Device: MacBook Air M2 (ARM64), macOS 26.3.1
  • App state: Background
  • Context: User browsed paginated book content, navigated away, app went to background. Crash occurred on DartWorker thread during statement finalization.
Thread: DartWorker (crashed)
  at sqlite3_finalize        +32
  at <obfuscated dart frame>
  at <obfuscated dart frame>
  at <obfuscated dart frame>
  at <obfuscated dart frame>
  at <obfuscated dart frame>
  at <obfuscated dart frame>
  at <obfuscated dart frame>
  at <obfuscated dart frame>
  at _pthread_start
  at thread_start

Signal: EXC_BAD_ACCESS (KERN_INVALID_ADDRESS)

Crash 2: sqlite3VdbeDelete SIGABRT (double-free)

  • Device: MacBook Air 2017 (x86_64), macOS 12.7.6
  • App state: Foreground
  • Context: User was rapidly scrolling through paginated content (many sequential read queries). Crash occurred on DartWorker thread.
Thread: DartWorker (crashed)
  at __pthread_kill
  at pthread_kill
  at abort
  at malloc_vreport
  at malloc_zone_error
  at free_large
  at sqlite3VdbeDelete         +1135
  at sqlite3_finalize
  at <obfuscated dart frame>
  at <obfuscated dart frame>
  at <obfuscated dart frame>
  at <obfuscated dart frame>
  at <obfuscated dart frame>
  at <obfuscated dart frame>
  at <obfuscated dart frame>
  at _pthread_start
  at thread_start

Signal: SIGABRT (ABORT)
Crash info: "pointer 0x7f7bb3500000 being freed was not allocated"

Analysis

Both crashes point to memory corruption in prepared statement lifecycle management within the background isolate:

  • Crash 1: sqlite3_finalize attempts to access freed memory (use-after-free on statement handle)
  • Crash 2: sqlite3VdbeDelete (called by sqlite3_finalize) attempts to free memory that was already freed (double-free)

This is low frequency (3 events across 3 users over 90 days) but both occurrences are on macOS using system SQLite (no sqlite3_flutter_libs). The crashes are 100% on the DartWorker thread, confirming they occur inside the background isolate created by createBackgroundConnection.

Possibly relevant: drift 2.28.1 introduced "Cache prepared statements by default" — could cached statement reuse interact poorly with finalization timing?

Expected behavior

sqlite3_finalize should safely finalize prepared statements without memory access violations.

Steps to reproduce

We have not been able to reproduce this locally. The crashes are observed via Firebase Crashlytics on production macOS builds. The usage pattern is:

  1. Open the app on macOS
  2. Open paginated content that triggers many sequential read queries
  3. Rapidly scroll through content (triggering section-change queries)
  4. Optionally: put the app in background

The crash occurs intermittently during step 3 or 4.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions