Skip to content

Glossary

SQLite freeblock

Free space inside a SQLite b-tree page, typically left by a deleted record, whose first four bytes are overwritten and the rest left intact.

A freeblock is a run of unused bytes inside a SQLite b-tree page, most often the space of a cell (a row) that was deleted. SQLite keeps a page's freeblocks in a chain: bytes 1-2 of the page header hold the offset of the first freeblock, and each freeblock starts with two 2-byte big-endian values, the offset of the next freeblock (0 for the last one) and the freeblock's size. Gaps smaller than four bytes are too small for that header and are counted as fragmented bytes instead (file format).

When a row is deleted, SQLite writes those four header bytes over the start of the old cell, typically its payload-length and rowid varints, and leaves the rest untouched unless secure_delete is enabled.

Why it matters in investigations

In wpndatabase.db, Windows deletes a notification row when the toast is dismissed or expires. The row's bytes, including most of its payload XML, stay in the page as a freeblock until a new row needs that space. This is how a dismissed chat preview or security alert can be recovered hours or days later. Freeblocks can also merge with neighbouring free space or be partly overwritten, so a recovered row may be incomplete: treat it as a lead, label its source and corroborate it.

Example

Page header (leaf table b-tree page)
  0D      page type 0x0D: leaf table page
  0F 3A   first freeblock at offset 0x0F3A
  00 05   5 live cells
  0E 20   cell content area starts at 0x0E20
  00      0 fragmented free bytes

Freeblock at offset 0x0F3A
  00 00   next freeblock: none (last in chain)
  01 52   size: 0x152 = 338 bytes
  ...     rest of the deleted record: ... <toast launch="...

The parser reports a row carved from such a block as free space in page N.

The Windows Notification Parser carves freeblocks automatically; recovering deleted Windows notifications explains the method and its limits.