#[non_exhaustive]pub enum AnomalyKind {
Show 14 variants
NonZeroReservedSpace {
reserved: u8,
},
DeletedRecordRecovered {
page: u32,
offset: usize,
rowid: i64,
},
DroppedSchemaRecovered {
object_type: String,
name: String,
},
NonEmptyFreelist {
free_pages: u32,
},
WalUncheckpointedState {
overlaid_pages: u32,
},
PageCountMismatch {
header_pages: u32,
file_pages: u32,
},
HotJournal {
mx_page: u32,
journaled_pages: u32,
},
JournalRecoverable {
images: usize,
},
JournalChecksumMismatch {
pgnos: Vec<u32>,
total: usize,
},
JournalSchemaChange {
journal_cookie: u32,
db_cookie: u32,
},
JournalDuplicatePage {
pgnos: Vec<u32>,
},
JournalDbSizeDelta {
mx_page: u32,
current_pages: u32,
},
FreelistCountInconsistent {
declared: u32,
walked: Option<u32>,
},
ZeroedFreelistResidue {
zeroed: u32,
free_leaves: u32,
first_zeroed: u32,
},
}Expand description
The classified SQLite forensic anomalies this auditor can grade.
#[non_exhaustive] so WS-E can add carving / WAL / freelist variants without
a breaking change; downstream match arms must carry a _ arm.
Variants (Non-exhaustive)§
This enum is marked as non-exhaustive
NonZeroReservedSpace
The header’s reserved-space-per-page field is non-zero. Standard
SQLite leaves this at 0; a non-zero value is used by page-level
extensions (e.g. encryption such as SQLCipher/SEE, or checksum VFS) and
is worth flagging on an evidence database.
DeletedRecordRecovered
A record-shaped cell was recovered from unallocated / free space — consistent with a deleted row that has not yet been overwritten.
Fields
DroppedSchemaRecovered
A sqlite_master row was recovered from page-1 free space whose
definition is absent from the live schema — consistent with a dropped
(or replaced) table/index/view/trigger whose CREATE statement and
existence survive the drop under secure_delete=OFF.
Fields
NonEmptyFreelist
The freelist is non-empty: the database holds free (unallocated) pages.
Consistent with prior deletions (DELETE without VACUUM); those pages
may retain recoverable deleted records.
WalUncheckpointedState
A -wal sidecar carried committed-but-unflushed page versions that the
main database file does not yet reflect. Consistent with an evidence
database captured while a write transaction was checkpoint-pending; the
main file alone would under-report the true state.
PageCountMismatch
The in-header page count disagrees with the page count implied by the file length. Consistent with truncation, carving, or out-of-band modification of the database file.
Fields
HotJournal
A -journal with an intact header (valid magic) sits beside the database
— a hot journal. Consistent with an interrupted or in-progress write
transaction (crash, power loss, process kill, or acquisition captured
mid-write); SQLite would roll it back on next open, so the main db may
require rollback. The journal holds the pre-interruption state. (Design §6
item 1 — state the observation; never assert “anti-forensic”.)
Fields
JournalRecoverable
A committed PERSIST -journal (header zeroed, bodies intact) carries
recoverable pre-images. Consistent with a normally-committed transaction
whose deleted/modified rows remain recoverable (design §6 item 2).
JournalChecksumMismatch
One or more journal page records failed the pager.c checksum (Tier A
only — Tier B has no nonce to verify against). Consistent with corruption,
a torn page (power-loss mid-sector), or post-write modification of the
journal (design §6 item 3).
Fields
JournalSchemaChange
The journal’s prior page-1 image carries a different schema cookie
(file-header offset 40, 4-byte BE) than the live database. The cookie
advances only on CREATE/DROP/ALTER, so a difference is consistent
with a DDL change in the last transaction; the prior schema is recoverable
(design §6 item 6). Page 1 alone is NOT sufficient — it is journaled on
nearly every write (the change-counter / freelist-count / db-size header
fields update routinely), so the cookie comparison, not page-1 presence,
is the DDL signal.
Fields
Schema cookie in the journal’s prior page-1 image (offset 40, BE).
Schema cookie in the live database’s page 1 (offset 40, BE).
JournalDuplicatePage
A pgno appeared more than once across the journal’s page records. The
spec journals a page at most once, so a repeat is consistent with
corruption, a savepoint/super-journal artifact, or tampering (design §6
item 9).
Fields
JournalDbSizeDelta
The database page count recorded at transaction start (mxPage, Tier A
only) differs from the current page count: the last transaction changed
the db size. mxPage < current ⇒ growth (INSERTs); mxPage > current ⇒
shrink, consistent with auto-vacuum/incremental-vacuum or truncation — NOT
an ordinary DELETE (design §6 item 5).
Fields
FreelistCountInconsistent
The free-page count declared in the header (offset 36) disagrees with the count obtained by walking the freelist trunk chain — or the chain is unwalkable (out-of-range/cyclic trunk pointer). The header field is a claim; the walk verifies it. A mismatch is consistent with freelist tampering (a hand-edited count to hide freed pages) or corruption (design §2.1 — distrust the header).
Fields
ZeroedFreelistResidue
Freed freelist leaf pages are entirely zero. A leaf page keeps its
former content byte-for-byte, so an all-zero freed leaf means the deleted
records it held were overwritten with zeros — residue deliberately
destroyed. Consistent with secure_delete=ON or a manual wipe (design
§2.1); it is a fingerprint of destruction, never proof of intent.
Implementations§
Trait Implementations§
Source§impl Clone for AnomalyKind
impl Clone for AnomalyKind
Source§fn clone(&self) -> AnomalyKind
fn clone(&self) -> AnomalyKind
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read more