@@ -30,7 +30,12 @@ CFLAGS="${CFLAGS} -UNDEBUG"
3030# We use some internal CPython API.
3131CFLAGS=" ${CFLAGS} -IInclude/internal/"
3232
33+ # Build all stdlib C extension modules statically into libpython
34+ # rather than as shared .so files, so they are linked into the fuzzers.
35+ export MODULE_BUILDTYPE=static
36+
3337FLAGS=()
38+ FLAGS+=(" --disable-test-modules" )
3439case $SANITIZER in
3540 address)
3641 FLAGS+=(" --with-address-sanitizer" )
@@ -49,19 +54,41 @@ case $SANITIZER in
4954esac
5055./configure " ${FLAGS[@]:- } " --prefix $OUT
5156
57+ # When building modules statically, HACL* crypto object files must be linked
58+ # via static archives (.a) instead of raw .o files to avoid duplicate symbols
59+ # across _blake2, _sha*, _hmac modules that share HACL* objects.
60+ # Only patch the MODULE_ dependency lines, not the LIBHACL variable definitions.
61+ sed -i ' /^MODULE__/s/LIB_SHARED/LIB_STATIC/g' Makefile
62+
5263# We use altinstall to avoid having the Makefile create symlinks
5364make -j$( nproc) altinstall
5465
66+ # When modules are statically linked into libpython, the fuzzer binaries
67+ # need the system libraries that those modules depend on (e.g. -lsqlite3,
68+ # -lz, -lssl). These are tracked in the Makefile's MODLIBS variable but
69+ # are not included by python-config --ldflags.
70+ PYTHON=$( ls $OUT /bin/python3.* | grep -v config | head -1)
71+ MODLIBS=$( $PYTHON -c " import sysconfig; print(sysconfig.get_config_var('MODLIBS'))" )
72+
5573FUZZ_DIR=Modules/_xxtestfuzz
5674for fuzz_test in $( cat $FUZZ_DIR /fuzz_tests.txt)
5775do
76+ # Template fuzzers have their own .c file; original targets use fuzzer.c
77+ if [ -f " $FUZZ_DIR /${fuzz_test} .c" ]; then
78+ FUZZ_SOURCE=" $FUZZ_DIR /${fuzz_test} .c"
79+ FUZZ_DEFINES=" "
80+ else
81+ FUZZ_SOURCE=" $FUZZ_DIR /fuzzer.c"
82+ FUZZ_DEFINES=" -D _Py_FUZZ_ONE -D _Py_FUZZ_$fuzz_test "
83+ fi
84+
5885 # Build (but don't link) the fuzzing stub with a C compiler
59- $CC $CFLAGS $( $OUT /bin/python* -config --cflags) $FUZZ_DIR /fuzzer.c \
60- -D _Py_FUZZ_ONE -D _Py_FUZZ_ $fuzz_test -c -Wno-unused-function \
86+ $CC $CFLAGS $( $OUT /bin/python* -config --cflags) $FUZZ_SOURCE \
87+ $FUZZ_DEFINES -c -Wno-unused-function \
6188 -o $WORK /$fuzz_test .o
6289 # Link with C++ compiler to appease libfuzzer
6390 $CXX $CXXFLAGS -rdynamic $WORK /$fuzz_test .o -o $OUT /$fuzz_test \
64- $LIB_FUZZING_ENGINE $( $OUT /bin/python* -config --ldflags --embed)
91+ $LIB_FUZZING_ENGINE $( $OUT /bin/python* -config --ldflags --embed) $MODLIBS
6592
6693 # Zip up and copy any seed corpus
6794 if [ -d " ${FUZZ_DIR} /${fuzz_test} _corpus" ]; then
0 commit comments