-
Type:
Bug
-
Resolution: Fixed
-
Priority:
Major - P3
-
Affects Version/s: None
-
Component/s: Checkpoints
-
None
-
Environment:Windows host with WSL (Ubuntu 24.04), GCC 13.3.0, AddressSanitizer enabled for repro
-
Storage Engines - Persistence
-
485.899
-
None
-
1
-
v8.3, v8.0, v7.0
Problem:
In __checkpoint_mark_skip the code reads (ckpt - 1)->name before checking
that the checkpoint list has at least two entries. When the list is empty (only
the NULL sentinel), ckpt == ckptbase after WT_CKPT_FOREACH, so (ckpt - 1)
is an out-of-bounds read. This is undefined behavior and is caught by ASan in a
minimal repro.
Root Cause
The unconditional dereference (ckpt - 1)->name appears before the guard
ckpt > ckptbase + 1 that would make it safe:
/* Bug */
const char *name = (ckpt - 1)->name; // evaluated unconditionally
if (ckpt > ckptbase + 1 && deleted < 2 && // guard comes too late
(strcmp(name, (ckpt - 2)->name) == 0 || ...
In the current production call path __checkpoint_lock_dirty_tree always
appends a new entry before calling __checkpoint_mark_skip so the list is
never empty at runtime. The bug is therefore latent the code is fragile
and will become immediately exploitable if the call-site guarantee is ever
relaxed by a refactor.
Move the dereference inside the bounds-checked branch:
/* Fix */
if (ckpt > ckptbase + 1 && deleted < 2) {
const char *name = (ckpt - 1)->name; // list has ≥ 2 entries
if (strcmp(name, (ckpt - 2)->name) == 0 ||
(WT_PREFIX_MATCH(name, WT_CHECKPOINT) &&
WT_PREFIX_MATCH((ckpt - 2)->name, WT_CHECKPOINT)))
}
A minimal C repro compiled with ASan confirms the out-of-bounds read pattern
when __checkpoint_mark_skip receives an empty list
- related to
-
WT-17634 SIGSEGV in __wt_checkpoint_tree_reconcile_update reached from eviction-time reconcile
-
- Needs Scheduling
-
-
WT-17607 17.89% increase in disagg_step_up_time in Variant amazon2023-perf-tests-arm64-only for Task cppsuite-disagg-failover-perf-append in Test test_disagg_failover_perf
-
- Closed
-