-
Type:
Task
-
Resolution: Unresolved
-
Priority:
Major - P3
-
None
-
Affects Version/s: None
-
Component/s: Observability
-
None
-
Storage Engines - Transactions
-
220.411
-
SE Transactions - 2026-09-25
-
3
__wt_overwrite_and_free() / _wt_overwrite_and_free_len() functions scribble WT_DEBUG_BYTE (0xab) over a structure before freeing it, making use-after-free bugs deterministic and easier to identify. Today this is gated on HAVE_DIAGNOSTIC, so it is absent from every release build.
Give this code its own switch so it can be enabled independently of a full diagnostic build.
There are 15 call sites (11 + 4 _len):
| File:line | Object |
|---|---|
| block_open.c:140 | block |
| block_mgr.c:350 | bm |
| block_cache.c:540 | blkcache_item |
| bt_handle.c:258 | btree |
| bt_read.c:172, bt_delete.c:437, rec_child.c:183 | ref->page_del |
| bt_split.c:44 | split page-index (_len) |
| bt_discard.c:132 | page disk image (_len, dsk->mem_size) |
| bt_discard.c:134 | page |
| bt_discard.c:360 | ref (_len, WT_REF_CLEAR_SIZE) |
| conn_dhandle.c:168 | dhandle |
| cur_std.c:1145 | cursor |
| session_dhandle.c:98 | dhandle_cache |
| generation.c:432 | split-generation stash (_len) |
Currently on release builds, this call defaults to wt_free, so it could present as silent data corruption that crashes arbitrarily at a later point. This makes the bugs expensive to diagnose in production.
WT_DEBUG_BYTE would fault immediately and never present as valid memory. Proposed change:
Option 1: debug_mode=(overwrite_free=true)
debug_mode is an existing config category with 15 sub-options, backed by WT_CONN_DEBUG_* flags. One of them realloc_malloc=true already does this operation of using __wt_explicit_overwrite
if (session != NULL && FLD_ISSET(S2C(session)->debug_flags, WT_CONN_DEBUG_REALLOC_MALLOC) &&
(bytes_allocated_ret != NULL)) {
if ((p = malloc(bytes_to_allocate)) == NULL)
WT_RET_MSG(session, __wt_errno(), "memory allocation of %" WT_SIZET_FMT " bytes failed",
bytes_to_allocate);
if (tmpp != NULL) {
memcpy(p, tmpp, *bytes_allocated_ret);
__wt_explicit_overwrite(tmpp, bytes_allocated);
__wt_free(session, tmpp);
}
Option 2: dedicated CMake option
HAVE_REF_TRACK does something similar where we have a diagnostic sub-feature, independently switchable from diagnostic builds.
Performance Impact:
We should not enable both macro variants with a single switch. Since some of the paths are hot. Either use two separate switches, or cap the _len variant:
__wt_explicit_overwrite(p, WT_MIN(len, WT_POISON_MAX));
Poisoning the first 64–128 bytes destroys the WT_PAGE_HEADER, which is read first.
Enabling this converts any currently-benign stale read into a hard crash, could potentially affect current non-crashing nodes. We should also confirm if there is a significant performance impact from turning this on in production builds.