Skip to content
Tech News
← Back to articles

How to corrupt an SQLite database file

read original more articles
Why This Matters

While SQLite databases are designed to be resilient against corruption, certain vulnerabilities—such as external file overwrites or improper file handling—can still lead to data corruption. Understanding these risks is crucial for developers and users to implement safeguards and maintain data integrity in their applications. Proper management of file descriptors and access controls can significantly reduce the likelihood of database corruption.

Key Takeaways

Overview

An SQLite database is highly resistant to corruption. If an application crash, or an operating-system crash, or even a power failure occurs in the middle of a transaction, the partially written transaction should be automatically rolled back the next time the database file is accessed. The recovery process is fully automatic and does not require any action on the part of the user or the application.

Though SQLite is resistant to database corruption, it is not immune. This document describes the various ways that an SQLite database might go corrupt.

1. File overwrite by a rogue thread or process

SQLite database files are ordinary disk files. That means that any process can open the file and overwrite it with garbage. There is nothing that the SQLite library can do to defend against this.

1.1. Continuing to use a file descriptor after it has been closed

We have seen multiple cases where a file descriptor was open on a file, then that file descriptor was closed and reopened on an SQLite database. Later, some other thread continued to write into the old file descriptor, not realizing that the original file had been closed already. But because the file descriptor had been reopened by SQLite, the information that was intended to go into the original file ended up overwriting parts of the SQLite database, leading to corruption of the database.

One example of this occurred circa 2013-08-30 on the canonical repository for the Fossil DVCS. In that event, file descriptor 2 (standard error) was being erroneously closed (by stunnel, we suspect) prior to sqlite3_open_v2() so that the file descriptor used for the repository database file was 2. Later, an application bug caused an assert() statement to emit an error message by invoking write(2,...). But since file descriptor 2 was now connected to a database file, the error message overwrote part of the database. To guard against this kind of problem, SQLite version 3.8.1 (2013-10-17) and later refuse to use low-numbered file descriptors for database files. (See SQLITE_MINIMUM_FILE_DESCRIPTOR for additional information.)

Another example of corruption caused by using a closed file descriptor was reported by facebook engineers in a blog post on 2014-08-12.

Another example of this error was reported against Fossil on 2019-07-11. A file descriptor would be opened for debugging output, but then closed and reopened by SQLite. But the debugging logic continued to write into the original file descriptor. See the forum discussion for the bug report and a link to the fix.

... continue reading