mirror of
https://github.com/DeusData/codebase-memory-mcp.git
synced 2026-11-03 08:03:38 +08:00
fix(mem): the parked result image is declared defined for MemorySanitizer
The MSan lane on 9724d903 stopped in the extraction suite's spill
round-trip test: uninitialized bytes in fwrite at offset 4087 of a
6,952-byte region, the parked result's arena block (the stack overflow
that followed is MemorySanitizer's own report path failing on the nested
bug). The park writes a result as an opaque image: the record header, a
struct copy, and the compacted arena block. Both carry padding bytes no
code ever wrote, inside structs and between objects, and MSan tracks that
mark through the compaction's memcpy, so zeroing the destination block
only moved the report (offset 6714 in the local MSan container). The
image is read back whole and never interpreted byte by byte; the padding
content is irrelevant on disk.
Under MSan the header and the block are declared defined right before
the write (__msan_unpoison, compiled in only when the build is
instrumented); every other build compiles the annotation to nothing. The
exact block is also zeroed once when it is created, so the gaps between
objects are deterministic in the spill file.
Verification: extraction, arena and parallel suites under ASan on the
fixed tree; the extraction suite in the local MSan container image
passes 348 / 0 with no sanitizer report (it reproduced the CI report exactly before the fix).
Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
This commit is contained in:
@@ -21,6 +21,24 @@
|
||||
#include "foundation/log.h"
|
||||
#include "foundation/mem_core.h"
|
||||
|
||||
/* The park writes a result as an opaque image: the record header (a struct
|
||||
* copy) and the compacted arena block. Both carry padding bytes no code ever
|
||||
* wrote -- inside structs, between objects -- and MemorySanitizer tracks
|
||||
* that mark through the compaction's memcpy, so it refuses the fwrite of an
|
||||
* image that is read back whole and never interpreted byte by byte (CI MSan
|
||||
* lane on #2202: offset 4087, then 6714, of a 6,952-byte block). Under MSan
|
||||
* the image is declared defined right before the write; every other build
|
||||
* compiles this to nothing. */
|
||||
#if defined(__has_feature)
|
||||
#if __has_feature(memory_sanitizer)
|
||||
#include <sanitizer/msan_interface.h>
|
||||
#define SPILL_IMAGE_DEFINED(p, n) __msan_unpoison((p), (n))
|
||||
#endif
|
||||
#endif
|
||||
#ifndef SPILL_IMAGE_DEFINED
|
||||
#define SPILL_IMAGE_DEFINED(p, n) ((void)0)
|
||||
#endif
|
||||
|
||||
#include <stdatomic.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
@@ -133,6 +151,8 @@ bool cbm_result_spill_park(cbm_result_spill_t *sp, int writer, int slot, CBMFile
|
||||
hdr.old_base = (uint64_t)(uintptr_t)result->arena.blocks[0];
|
||||
hdr.header = *result;
|
||||
hdr.header.cached_tree = NULL; /* never on disk: the loader gets no tree */
|
||||
SPILL_IMAGE_DEFINED(&hdr, sizeof(hdr));
|
||||
SPILL_IMAGE_DEFINED(result->arena.blocks[0], hdr.block_len);
|
||||
cbm_mutex_lock(&f->mu);
|
||||
uint64_t offset = f->end;
|
||||
bool ok = SPILL_SEEK(f->fp, offset) == 0 && fwrite(&hdr, sizeof(hdr), 1, f->fp) == 1 &&
|
||||
|
||||
@@ -45,6 +45,15 @@ void cbm_arena_init_exact(CBMArena *a, size_t bytes) {
|
||||
size_t block = (bytes + ARENA_ALIGN) & ~(size_t)ARENA_ALIGN;
|
||||
cbm_arena_init_sized(a, block);
|
||||
a->grow_size = CBM_ARENA_DEFAULT_BLOCK_SIZE;
|
||||
/* An exact block is a compacted result's image and may be written to
|
||||
* disk whole (result_spill): the alignment gaps between objects and the
|
||||
* padding inside structs are never written by the copy, and MemorySanitizer
|
||||
* refuses an fwrite of uninitialized bytes (CI MSan lane on #2202, offset
|
||||
* 4087 of a 6,952-byte block). Zeroed once here, every byte of the image
|
||||
* is defined; the cost is one pass over memory the copy is about to touch. */
|
||||
if (a->blocks[0]) {
|
||||
memset(a->blocks[0], 0, a->block_sizes[0]);
|
||||
}
|
||||
}
|
||||
|
||||
static int arena_grow(CBMArena *a, size_t min_size) {
|
||||
|
||||
Reference in New Issue
Block a user