fix(msan): scope the zstd stdint workaround to the zstd object

The previous fix put -include stdint.h on the lane's global SANITIZE
line. That traded one vendored compile break for another: force-including
a libc header ahead of every source file freezes glibc's feature-test
macros before sqlite3.c can set _GNU_SOURCE for itself, and its view of
libc loses MREMAP_MAYMOVE and nanosleep (17 errors on the x86-64 CI
leg).

The workaround only ever had one legitimate target -- the zstd
amalgamation whose MEMORY_SANITIZER block lost its stdint re-include --
so it now rides a per-object hook (ZSTD_EXTRA_CFLAGS) that the MSan lane
sets and every other build leaves empty. sqlite3.c compiles exactly as
before in every lane.

Verified locally that zstd compiles with the hook and the default rule
stays untouched; the MSan leg itself is x86-64-only, so CI is its
verification venue.

Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
This commit is contained in:
Martin Vogel
2026-08-03 17:02:51 +02:00
parent 5adcfd296c
commit 6a0adb4430
2 changed files with 16 additions and 14 deletions
+9 -1
View File
@@ -787,10 +787,18 @@ $(BUILD_DIR)/tsan_lz4hc.o: $(CBM_DIR)/vendored/lz4/lz4hc.c | $(BUILD_DIR)
$(CC) -std=c11 -D_DEFAULT_SOURCE -g -O1 $(TSAN_SANITIZE) -w -I$(CBM_DIR)/vendored/lz4 -c -o $@ $<
# Vendored zstd (test build)
# ZSTD_EXTRA_CFLAGS: hook for sanitizer lanes. The MSan lane needs
# `-include stdint.h` for THIS object only: zstd's MEMORY_SANITIZER-guarded
# block declares __msan_test_shadow returning intptr_t, but the amalgamator
# collapsed the `#define ZSTD_DEPS_NEED_STDINT` re-include that should supply
# it. The flag cannot go on the global SANITIZE line: force-including a libc
# header ahead of a source file freezes glibc's feature-test macros before
# files like sqlite3.c set _GNU_SOURCE themselves, which strips
# MREMAP_MAYMOVE/nanosleep out of their view of libc.
ZSTD_OBJ_TEST = $(BUILD_DIR)/test_zstd.o
ZSTD_OBJ_TSAN = $(BUILD_DIR)/tsan_zstd.o
$(BUILD_DIR)/test_zstd.o: $(CBM_DIR)/vendored/zstd/zstd.c | $(BUILD_DIR)
$(CC) -std=c11 -D_DEFAULT_SOURCE -g -O1 $(SANITIZE) -w -I$(CBM_DIR)/vendored/zstd -c -o $@ $<
$(CC) -std=c11 -D_DEFAULT_SOURCE -g -O1 $(SANITIZE) $(ZSTD_EXTRA_CFLAGS) -w -I$(CBM_DIR)/vendored/zstd -c -o $@ $<
$(BUILD_DIR)/tsan_zstd.o: $(CBM_DIR)/vendored/zstd/zstd.c | $(BUILD_DIR)
$(CC) -std=c11 -D_DEFAULT_SOURCE -g -O1 $(TSAN_SANITIZE) -w -I$(CBM_DIR)/vendored/zstd -c -o $@ $<
+7 -13
View File
@@ -41,19 +41,12 @@ if [ "$MSAN_ORIGINS" = "0" ]; then
else
MSAN_ORIGIN_FLAG="-fsanitize-memory-track-origins=$MSAN_ORIGINS"
fi
# -include stdint.h: vendored zstd carries an MSan-only block (guarded by
# MEMORY_SANITIZER) that declares __msan_test_shadow returning intptr_t. It
# reaches for the type with the usual
# #define ZSTD_DEPS_NEED_STDINT
# #include "zstd_deps.h"
# idiom, but the amalgamator that produced zstd.c collapsed that second
# include into a "skipping file" comment, so the define never pulls anything
# in and intptr_t is undeclared. Only this lane compiles that block, and only
# where <stddef.h> does not happen to drag stdint.h in transitively -- which
# is why it builds on aarch64 glibc and fails on x86-64. Forcing the header
# is a lane-local fix; patching the vendored amalgamation would be undone by
# the next re-vendor.
MSAN_SAN="-fsanitize=memory $MSAN_ORIGIN_FLAG -fno-omit-frame-pointer -include stdint.h -isystem $MSAN_PREFIX/include"
MSAN_SAN="-fsanitize=memory $MSAN_ORIGIN_FLAG -fno-omit-frame-pointer -isystem $MSAN_PREFIX/include"
# Scoped to the zstd object ONLY (see the ZSTD_EXTRA_CFLAGS note in
# Makefile.cbm): zstd's MSan block needs stdint.h that its amalgamation lost,
# but force-including it globally freezes glibc feature-test macros before
# sqlite3.c can set _GNU_SOURCE, breaking that compile instead.
ZSTD_EXTRA="-include stdint.h"
# Always clean: make does not encode flags into dependencies, so a build dir
# populated under different stdlib/sanitizer flags silently mixes objects
@@ -64,6 +57,7 @@ make -f Makefile.cbm clean-c BUILD_DIR=build/msan >/dev/null 2>&1 || true
make -j"$(nproc)" -f Makefile.cbm build/msan/test-runner \
CC=clang CXX=clang++ BUILD_DIR=build/msan \
SANITIZE="$MSAN_SAN" \
ZSTD_EXTRA_CFLAGS="$ZSTD_EXTRA" \
CXX_STDLIB_FLAGS="-stdlib=libc++ -nostdinc++ -isystem $MSAN_PREFIX/include/c++/v1" \
CXX_STDLIB="-L$MSAN_PREFIX/lib -Wl,-rpath,$MSAN_PREFIX/lib -lc++ -lc++abi"