Skip to content

Fix WAL checksum entry-buffer resize dropping buffered bytes - #959

Merged
adsharma merged 1 commit into
mainfrom
fix-771-wal-checksum-resize
Sep 11, 2026
Merged

Fix WAL checksum entry-buffer resize dropping buffered bytes#959
adsharma merged 1 commit into
mainfrom
fix-771-wal-checksum-resize

Conversation

@adsharma

Copy link
Copy Markdown
Contributor

Fixes #771.

Root cause

A single WAL record larger than ~4KB failed replay with Checksum verification failed / Corrupted wal file. Read out invalid WAL record type.

ChecksumWriter/ChecksumReader accumulate each WAL record in a 4KB entry buffer and grow it in resizeBufferIfNeeded. The resize allocated a fresh uninitialized buffer without copying the already-buffered bytes, so the record-length prefix was lost on write (corrupting the WAL file on disk) and the checksum was computed over garbage on read. The 4KB threshold is the entry buffer's initial size (LBUG_PAGE_SIZE), matching the issue's per-record threshold observation. The same-process/GC/file-hash observations in the report follow from the corruption living in the WAL file plus uninitialized-memory nondeterminism — I reproduced the failure at the C++ level and even a fresh-process reopen failed on the corrupted WAL.

Fix

Copy the valid prefix into the new buffer on resize (same pattern as ColumnChunkData::resize), in both checksum_writer.cpp and checksum_reader.cpp.

Tests

  • New regression tests WalTest.LargeWALRecordReplay and WalTest.LargeWALRecordReplayWithPreviousDBAlive (5KB STRING record, replay after close and while the first DB is still alive). Verified they fail without the fix with the exact error from the issue, and pass with it.
  • Full WalTest suite: 31/31 pass. Broader CI will cover the rest.

ChecksumWriter and ChecksumReader accumulate each WAL record in a 4KB
entry buffer and grow it via resizeBufferIfNeeded when a record exceeds
that size. The resize allocated a fresh (uninitialized) buffer without
copying the bytes already accumulated, so any single WAL record larger
than ~4KB was corrupted on write (record-length prefix lost) and failed
verification on replay with 'Checksum verification failed' / 'Corrupted
wal file. Read out invalid WAL record type'.

Copy the valid prefix into the new buffer on resize, matching the
pattern used by ColumnChunkData::resize.

Adds regression tests writing a 5KB STRING record and replaying the WAL,
both after close and while the original Database is still alive.

Fixes #771
@adsharma
adsharma force-pushed the fix-771-wal-checksum-resize branch from 6e8daf7 to 79ec03c Compare September 11, 2026 23:46
@adsharma
adsharma merged commit 0b4f086 into main Sep 11, 2026
2 of 3 checks passed
@adsharma
adsharma deleted the fix-771-wal-checksum-resize branch September 11, 2026 23:47
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.

Reopening the same database file in the same process fails WAL replay when the WAL contains records >4KB (graceful close, not crash)

1 participant