Skip to content

PRAGMA cipher_migrate fails when a valid database filename contains a single quote #610

Description

@DBFuzz

Version and environment

Reproduced on SQLCipher commit 810db22f575ee7cf94ea96a3e91622b5fcece3dc, Linux amd64, with SQLite 3.53.3 / SQLCipher 4.17.0 Community and the bundled SQLCipher 3.0 testkey fixture.

Describe the bug

The migration code derives <database filename>-migrated and places that path directly inside ATTACH DATABASE '%s'. A valid filename containing ' therefore breaks the internal SQL string. The identical old-format database migrates under a normal filename but fails when only its filename changes to include a single quote.

Minimal reproduction

bash sqlcipher-026-pragma-cipher-migrate-fails-for-valid-old-format-datab-bee6fa14/poc/revalidate_sqlcipher_026.sh

The essential setup is:

cp sqlcipher-3.0-testkey.db /tmp/c026-normal.db
cp sqlcipher-3.0-testkey.db "/tmp/c026-quote'key.db"
sqlcipher /tmp/c026-normal.db "PRAGMA key='testkey'; PRAGMA cipher_migrate; SELECT count(*) FROM sqlite_schema;"
sqlcipher "/tmp/c026-quote'key.db" "PRAGMA key='testkey'; PRAGMA cipher_migrate; SELECT count(*) FROM sqlite_schema;"

The wrapper also reopens both files after migration.

Actual behavior/output

normal_schema_count|1
normal_status|0
normal_reopen_count|1
quote_status|1
quote_reopen_status|1

Stderr includes sqlcipher_codec_ctx_migrate: attach failed, error code 1, file is not a database, and failure to delete /tmp/c026-quote'key.db-migrated.

Expected behavior

Both files contain identical valid legacy databases, and ' is valid in the POSIX filename. cipher_migrate should safely quote/bind its internally derived path and migrate both copies.

Impact and scope

Users cannot migrate valid legacy databases at paths containing a single quote. Applications may need unsafe renaming workarounds and can be left with a failed migration artifact.

Relevant source/root cause

src/sqlcipher.c:2185 derives the migration filename. Around :2204, it constructs ATTACH DATABASE '%s' as migrate; without escaping the path as an SQL string. The subsequent failure aligns with this attach step; existing compatibility tests use only ordinary filenames.

Suggested regression test

Copy a known SQLCipher 3 fixture to a path containing ', run cipher_migrate, and verify current-format reopen/query success. Add other SQL-string-special path characters and assert cleanup of the -migrated file on both success and failure.

Reproduction bundle

Attached: sqlcipher-026-pragma-cipher-migrate-fails-for-valid-old-format-datab-bee6fa14_attachment.zip. It contains the focused PoC, validation evidence, and candidate metadata.

sqlcipher-026-pragma-cipher-migrate-fails-for-valid-old-format-datab-bee6fa14_attachment.zip

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions