Skip to content

Three small fixes: direct-only config functions, dispatch table order, journal encryption errors - #298

Merged
utelle merged 3 commits into
utelle:mainfrom
SchwarzDigits:fix/directonly-dispatch-journal
Nov 2, 2026
Merged

utelle merged 3 commits into
utelle:mainfrom
SchwarzDigits:fix/directonly-dispatch-journal

Conversation

@mtrossbach

Copy link
Copy Markdown
Contributor

Three independent fixes, one commit each.

Register sqlite3mc_config and sqlite3mc_codec_data as direct-only
Both functions were registered as deterministic and could be called from the schema of any database file. With the default trusted_schema=ON, a view or trigger in a foreign database file could switch the connection to RC4, turn off the HMAC check or lower kdf_iter, and a database attached afterwards with ATTACH ... KEY was created with these settings without an error. They are now registered with SQLITE_DIRECTONLY, as the VLE functions already are.

Fix the order of two entry pairs in the core dispatch table
The initializer of sqlite3mcCoreApis had preupdate_new before preupdate_old and win32_set_directory16 before win32_set_directory8, the struct declares them the other way round. With SQLITE3MC_USE_DISPATCH_TABLE, sqlite3_preupdate_old() returned the new value and sqlite3_preupdate_new() the old one.

Check the codec that encrypted the journal page
mcWriteMainJournal and mcWriteSubJournal checked the last error of the journal file's codec, which is always NULL, so a failed encryption went unnoticed and the page buffer was written anyway. If the cipher fails before it encrypts, that buffer still holds the plaintext page. Same change as in 4afae8a for sqlite3mcPagerCodec and mcWriteWal.

Testing (macOS arm64, flags from Makefile.am):

  • The SQL scripts from the CI, cryptotest, the four tempfiletest runs and oomtest pass.
  • A view that calls sqlite3mc_config('cipher','rc4') no longer changes the connection: reading it fails with "unsafe use of sqlite3mc_config()". Direct calls work as before.
  • With SQLITE3MC_USE_DISPATCH_TABLE, sqlite3_preupdate_old() and sqlite3_preupdate_new() now return the old and the new value. The two Windows entries are only checked against the struct declaration, not built on Windows.
  • With an encrypt function that fails while a journal page is written, the plaintext page no longer reaches the journal file.

Both functions change or reveal the encryption settings of the
connection, but they were registered as deterministic and could be
called from the schema of any database file. With the default
trusted_schema=ON, a view or trigger in a foreign database file could
switch the connection to RC4, turn off the HMAC check or lower kdf_iter,
and a database attached afterwards with ATTACH ... KEY was created with
these settings without an error. Being deterministic also allowed their
use in expression indexes, although the result changes at run time.

Register them with SQLITE_DIRECTONLY instead of SQLITE_DETERMINISTIC,
as the VLE functions already are.
The initializer of sqlite3mcCoreApis listed sqlite3_preupdate_new before
sqlite3_preupdate_old, and sqlite3_win32_set_directory16 before
sqlite3_win32_set_directory8, while struct sqlite3mc_core_routines
declares them the other way round. With SQLITE3MC_USE_DISPATCH_TABLE,
sqlite3_preupdate_old() therefore returned the new value and
sqlite3_preupdate_new() the old one, and on Windows the two
set_directory functions were swapped.
mcWriteMainJournal and mcWriteSubJournal encrypt the page with the codec
of the main database, but checked the last error of the codec of the
journal file, which is always NULL. A failed encryption therefore went
unnoticed, and the page buffer was written to the journal anyway. If the
cipher fails before it encrypts, that buffer still holds the plaintext
copy of the page.

Check the codec that was used, as 4afae8a already does in
sqlite3mcPagerCodec and mcWriteWal.
@utelle
utelle merged commit d465a8e into utelle:main Nov 2, 2026
13 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants