From Dr. Richard Hipp:<p>There is a bug in versions 3.35.0 (2021-03-12) through
3.37.1 (2021-12-30) which could potentially cause database
corruption. Upgrading to version 3.37.2 (2022-01-06) or later is recommended.<p>## About the bug<p>In order to encounter this problem you must:<p>1. Change SQLite's default behavior so that it stores secondary journal
files in memory, rather than as temporary files on disk. Secondary
journals are stored on disk by default. To move to in-memory storage
you need to compile with [-DSQLITE_TEMP_STORE=2 or 3][1] or
set [PRAGMA journal_mode=MEMORY][2] at run-time.<p>2. Use the [SAVEPOINT][3] SQL statement to create nested transactions and
sometimes roll back those transactions using ROLLBACK TO.<p>3. You also need a measure of bad luck, as the problem is difficult to hit.<p>## Recommended fix.<p>The recommended fix for this problem is to upgrade to [version 3.37.2][4].
If that is not possible for you, you should at least consider applying
the [one-character patch][p1] to fix the problem.<p>## How this bug was created and how it was discovered<p>The bug arose from an enhancement that we installed in response to
[forum post e78ffd751185a67e][5]. Repeated use of SAVEPOINT and
ROLLBACK TO with an in-memory journal was causing excess memory
usage. The fix was to "truncate" the in-memory journals following
a ROLLBACK TO, in order to contain the memory growth.<p>The bug was first discovered (and [reported on this forum][6])
10 months later by researchers at the
Wingtecher Lab of Tsinghua University. Using the AFL++ fuzzer with
a custom mutator, they managed to cause an [assert() statement][7]
to fail. It turns out that assert() statement existed to verify that
the statement journals were operating correctly, and so the failure
of that assert() statement indicated a possible corruption bug. Further
analysis showed that corruption was possible, though it is difficult
to hit.<p>This bug is a sufficiently obscure corner case that it might have gone
unnoticed for many years, had it not been for SQLite's heavy use
of assert() statement to verify internal consistency, and for
Wingtecher Lab's ground-breaking analysis tools that found a way to
get one of those assert() statements to fail.<p>[1]: <a href="https://www.sqlite.org/compile.html#temp_store" rel="nofollow">https://www.sqlite.org/compile.html#temp_store</a>
[2]: <a href="https://www.sqlite.org/pragma.html#pragma_temp_store" rel="nofollow">https://www.sqlite.org/pragma.html#pragma_temp_store</a>
[3]: <a href="https://www.sqlite.org/lang_savepoint.html" rel="nofollow">https://www.sqlite.org/lang_savepoint.html</a>
[4]: <a href="https://www.sqlite.org/releaselog/3_37_2.html" rel="nofollow">https://www.sqlite.org/releaselog/3_37_2.html</a>
[p1]: <a href="https://sqlite.org/src/fdiff?v1=a85f0dc5c02a4245&v2=ff4336a98b05ede2&diff=1" rel="nofollow">https://sqlite.org/src/fdiff?v1=a85f0dc5c02a4245&v2=ff4336a9...</a>
[5]: <a href="https://sqlite.org/forum/forumpost/e78ffd751185a67e" rel="nofollow">https://sqlite.org/forum/forumpost/e78ffd751185a67e</a>
[6]: <a href="https://sqlite.org/forum/forumpost/d7338bf4901f1151" rel="nofollow">https://sqlite.org/forum/forumpost/d7338bf4901f1151</a>
[7]: <a href="https://www.sqlite.org/assert.html" rel="nofollow">https://www.sqlite.org/assert.html</a>
A database corruption bug in SQLite is like...A security issue in OpenBSD or a crash of a Debian 3 server...you remember where you were, when you first heard about it:-)
> What should have been a "<" operator was coded as "<=".<p>As always, off by one is problem! Thanks for massive assertion and fuzzing.