Skip to content

[fuzz] Add MemorySanitizer (MSAN) support to fuzz targets#72743

Open
Alami-Amine wants to merge 4 commits into
project-chip:masterfrom
Alami-Amine:AA/msan-fuzztests
Open

[fuzz] Add MemorySanitizer (MSAN) support to fuzz targets#72743
Alami-Amine wants to merge 4 commits into
project-chip:masterfrom
Alami-Amine:AA/msan-fuzztests

Conversation

@Alami-Amine

Copy link
Copy Markdown
Contributor

Summary

Adds MemorySanitizer (MSAN) support to the fuzz targets, building on the MSAN unit-test infrastructure from #71784. This makes both the legacy libFuzzer harnesses (chip_fuzz_target) and the pw_fuzzer / Google FuzzTest harnesses (chip_pw_fuzz_target) buildable and runnable under MSAN — locally for reproduction, and on OSS-Fuzz (which previously had the memory sanitizer disabled for this project due to uninstrumented dependencies).

MSAN requires every linked object to be instrumented, including the C++ runtime and third-party dependencies. The unit-test work (#71784) already provides an instrumented dependency sysroot (build_msan_sysroot.sh) and the sanitize_memory config; this change wires that into the fuzz build paths.

Changes

  • build_msan_sysroot.sh: add an --oss-fuzz mode that builds only the C dependencies (OpenSSL, zlib, libffi, pcre2, GLib) using the OSS-Fuzz compiler ($CC/$CXX) and $CFLAGS, and skips building libc++ — OSS-Fuzz ships its own instrumented libc++ (/usr/msan, applied via -stdlib=libc++), and reusing a libc++ built with a different clang would mismatch. The default local mode is unchanged.
  • Move is_msan / msan_sysroot declare_args from build/config/compiler/BUILD.gn to build/config/compiler/compiler.gni, so the fuzz templates and the pw_fuzzer toolchain (which import the .gni, but cannot import a BUILD.gn) can read is_msan.
  • Local libFuzzer targets (chip_fuzz_target): apply sanitize_memory instead of sanitize_address when is_msan is set. ASan and MSAN are mutually exclusive, and sanitize_memory is already applied globally via sanitize_default.
  • Local pw_fuzzer / FuzzTest targets: add a chip_pw_fuzz_msan toolchain arg that swaps pigweed's ASan for chip's sanitize_memory in the chip_pw_fuzztest toolchain (which does not consume chip's global sanitize_default).
  • build_examples: the msan modifier now composes with libfuzzer and pw-fuzztest; host.py drives the pw_fuzzer path via chip_pw_fuzz_msan and the libFuzzer / unit-test path via is_msan.

New buildable targets, e.g.:

scripts/build/build_examples.py --target linux-x64-tests-clang-pw-fuzztest-msan build
scripts/build/build_examples.py --target linux-x64-tests-clang-libfuzzer-msan build

(The OSS-Fuzz connectedhomeip project configuration — Dockerfile/build.sh/project.yaml — is updated in a companion change in the OSS-Fuzz repository; it invokes build_msan_sysroot.sh --oss-fuzz and re-enables the memory sanitizer.)

Testing

  • Built and ran the local targets under MSAN against the instrumented sysroot:
    • linux-x64-tests-clang-libfuzzer-msanfuzz-tlv-reader ran 30000 inputs to a clean Done, no MSAN report (links the instrumented libc++ and OpenSSL).
    • linux-x64-tests-clang-pw-fuzztest-msanfuzz-tlv-reader-pw fuzzed cleanly under MSAN.
  • Validated the --oss-fuzz path end-to-end in the OSS-Fuzz base image (SANITIZER=memory): the dependency sysroot builds with the OSS-Fuzz clang, all fuzz targets compile (legacy libFuzzer + per-case FuzzTest wrappers), and check_build passes.
  • gn gen succeeds for both new target flavors with --fail-on-unused-args; the default (non-MSAN) build paths are unchanged.

Builds on the MSAN unit-test infrastructure (project-chip#71784) so the fuzz targets can
build and run under MemorySanitizer, both locally and on OSS-Fuzz.

- build_msan_sysroot.sh: add an --oss-fuzz mode that builds only the C
  dependencies (OpenSSL/zlib/libffi/pcre2/GLib) with the OSS-Fuzz compiler
  ($CC/$CXX) and $CFLAGS, skipping libc++ (OSS-Fuzz ships an instrumented
  libc++ at /usr/msan, applied via -stdlib=libc++). The default local mode is
  unchanged.
- Move the is_msan / msan_sysroot build args from compiler/BUILD.gn to
  compiler.gni so the fuzz templates and the pw_fuzzer toolchain (which import
  the .gni) can read is_msan.
- Local libFuzzer targets (chip_fuzz_target): apply sanitize_memory instead of
  sanitize_address when is_msan is set (ASan and MSAN are mutually exclusive;
  sanitize_memory is supplied globally via sanitize_default).
- Local pw_fuzzer / FuzzTest targets: add a chip_pw_fuzz_msan toolchain arg
  that swaps pigweed's ASan for chip's sanitize_memory in the chip_pw_fuzztest
  toolchain (which does not consume the global sanitize_default).
- build_examples: the `msan` modifier now composes with `libfuzzer` and
  `pw-fuzztest`; host.py drives the pw_fuzzer path via chip_pw_fuzz_msan and
  the libFuzzer / unit-test path via is_msan.

Enables, for example:
  linux-x64-tests-clang-pw-fuzztest-msan
  linux-x64-tests-clang-libfuzzer-msan

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces support for building local pw_fuzzer and FuzzTest targets with MemorySanitizer (MSan) instead of AddressSanitizer (ASan). It refactors the GN build configuration to share MSan variables across toolchains, adds a new chip_pw_fuzz_msan flag, and updates the MSan sysroot build script to support OSS-Fuzz environments by utilizing the container's compiler and skipping the libc++ build. The review feedback points out that when configuring the sysroot dependencies (zlib, libffi, and pcre2), the script completely overrides LDFLAGS with "-fsanitize=memory". The reviewer recommends appending to the existing LDFLAGS instead, ensuring that critical environment-specific flags pre-configured by OSS-Fuzz are not discarded.

Comment thread scripts/build/build_msan_sysroot.sh Outdated
Comment thread scripts/build/build_msan_sysroot.sh Outdated
Comment thread scripts/build/build_msan_sysroot.sh Outdated
Append ${LDFLAGS:-} instead of overriding LDFLAGS when configuring the
autoconf deps (zlib/libffi/pcre2), so any flags set by the build environment
are kept. No-op for the local build (LDFLAGS unset there).
The GLib meson native file builds its c_args/cpp_args arrays by iterating
over $MSAN. The loop quoted "$MSAN", so every flag collapsed into a single
array element and meson passed the whole string to clang as one argument
("clang: error: unsupported argument ... to option '-fsanitize='"), breaking
the GLib dependency build in both the local and --oss-fuzz paths.

Split $MSAN explicitly with `read -ra` so each flag is its own array element.
This is also shellcheck-clean, so the intentional word-splitting won't get
re-quoted by a linter.
@github-actions

github-actions Bot commented Jun 25, 2026

Copy link
Copy Markdown

PR #72743: Size comparison from 413ff63 to 7c23a6f

Full report (33 builds for bl602, bl702, bl702l, cc13x4_26x4, cc32xx, efr32, esp32, nrfconnect, psoc6, qpg, realtek, stm32, telink)
platform target config section 413ff63 7c23a6f change % change
bl602 lighting-app bl602+mfd+littlefs+rpc FLASH 1099176 1099176 0 0.0
RAM 133418 133418 0 0.0
bl702 lighting-app bl702+eth FLASH 1085726 1085726 0 0.0
RAM 109029 109029 0 0.0
bl702l contact-sensor-app bl702l+mfd+littlefs FLASH 882218 882218 0 0.0
RAM 108596 108596 0 0.0
cc13x4_26x4 lighting-app LP_EM_CC1354P10_6 FLASH 777368 777368 0 0.0
RAM 103404 103404 0 0.0
lock-ftd LP_EM_CC1354P10_6 FLASH 790120 790120 0 0.0
RAM 108684 108684 0 0.0
pump-app LP_EM_CC1354P10_6 FLASH 739376 739376 0 0.0
RAM 97612 97612 0 0.0
pump-controller-app LP_EM_CC1354P10_6 FLASH 719548 719548 0 0.0
RAM 97644 97644 0 0.0
cc32xx air-purifier CC3235SF_LAUNCHXL FLASH 569654 569654 0 0.0
RAM 205112 205112 0 0.0
lock CC3235SF_LAUNCHXL FLASH 597214 597214 0 0.0
RAM 205272 205272 0 0.0
efr32 lighting-app BRD4187C FLASH 1094924 1094924 0 0.0
RAM 135256 135256 0 0.0
lock-app BRD4187C FLASH 995184 995184 0 0.0
RAM 131292 131292 0 0.0
BRD4338a FLASH 799809 799809 0 0.0
RAM 243432 243432 0 0.0
esp32 all-clusters-app c3devkit DRAM 99556 99556 0 0.0
FLASH 1626146 1626146 0 0.0
IRAM 94776 94776 0 0.0
nrfconnect all-clusters-app nrf52840dk_nrf52840 FLASH 844772 844772 0 0.0
RAM 157771 157771 0 0.0
psoc6 all-clusters cy8ckit_062s2_43012 FLASH 1750756 1750756 0 0.0
RAM 215492 215492 0 0.0
all-clusters-minimal cy8ckit_062s2_43012 FLASH 1626548 1626548 0 0.0
RAM 211604 211604 0 0.0
light cy8ckit_062s2_43012 FLASH 1470860 1470860 0 0.0
RAM 197436 197436 0 0.0
lock cy8ckit_062s2_43012 FLASH 1504308 1504308 0 0.0
RAM 225268 225268 0 0.0
qpg lighting-app qpg6200+debug FLASH 843156 843156 0 0.0
RAM 127908 127908 0 0.0
lock-app qpg6200+debug FLASH 782976 782976 0 0.0
RAM 118840 118840 0 0.0
realtek light-switch-app rtl8777g FLASH 689368 689368 0 0.0
RAM 101780 101780 0 0.0
lighting-app rtl8777g FLASH 730304 730304 0 0.0
RAM 102052 102052 0 0.0
stm32 light STM32WB5MM-DK FLASH 478976 478976 0 0.0
RAM 141492 141492 0 0.0
telink all-devices-app tl7218x FLASH 881716 881716 0 0.0
RAM 99716 99716 0 0.0
tlsr9118bdk40d FLASH 673322 673322 0 0.0
RAM 120848 120848 0 0.0
bridge-app tl7218x FLASH 734156 734156 0 0.0
RAM 97700 97700 0 0.0
light-app-ota-compress-lzma-factory-data tl3218x FLASH 800682 800682 0 0.0
RAM 42380 42380 0 0.0
light-app-ota-compress-lzma-shell-factory-data tl7218x FLASH 845822 845822 0 0.0
RAM 101492 101492 0 0.0
light-switch-app-ota-compress-lzma-factory-data tl7218x_retention FLASH 734714 734714 0 0.0
RAM 57824 57824 0 0.0
light-switch-app-ota-compress-lzma-shell-factory-data tlsr9528a FLASH 795802 795802 0 0.0
RAM 75176 75176 0 0.0
light-switch-app-ota-factory-data tl3218x_retention FLASH 734630 734630 0 0.0
RAM 34480 34480 0 0.0
lighting-app-ota-factory-data tlsr9118bdk40d FLASH 615214 615214 0 0.0
RAM 118508 118508 0 0.0
lighting-app-ota-rpc-factory-data-4mb tlsr9518adk80d FLASH 842038 842042 4 0.0
RAM 97376 97376 0 0.0

@codecov

codecov Bot commented Jun 25, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 56.79%. Comparing base (44fb474) to head (7c23a6f).
⚠️ Report is 25 commits behind head on master.

Additional details and impacted files
@@            Coverage Diff             @@
##           master   #72743      +/-   ##
==========================================
+ Coverage   56.76%   56.79%   +0.03%     
==========================================
  Files        1634     1642       +8     
  Lines      112660   112757      +97     
  Branches    13144    13139       -5     
==========================================
+ Hits        63946    64040      +94     
- Misses      48714    48717       +3     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant