From c9725c6484be27465a41dac89de50a05ba59b26e Mon Sep 17 00:00:00 2001 From: Andrei Litvin Date: Wed, 3 May 2023 09:17:10 -0400 Subject: [PATCH] Building fuzzing logic was not well documented (#26298) * Add OSS fuzz as a fuzzing option for host builds * Fix unit tests * Fix fuzz targets for fake tests as well * Fix documentation and tests * Restyled by prettier-markdown * Restyled by autopep8 * Update docks * Restyled by prettier-markdown * Update text a bit to say unit tests and libfuzzer * Add ossfuzz docs * Restyle * Fix paths for scripts to add the leading . --------- Co-authored-by: Andrei Litvin Co-authored-by: Restyled.io --- docs/guides/BUILDING.md | 52 ++++++++++++++++++- scripts/build/build/targets.py | 8 +-- scripts/build/builders/host.py | 26 ++++++---- .../build/testdata/all_targets_linux_x64.txt | 4 +- 4 files changed, 75 insertions(+), 15 deletions(-) diff --git a/docs/guides/BUILDING.md b/docs/guides/BUILDING.md index 08900d3313e340..26ff8d59485e13 100644 --- a/docs/guides/BUILDING.md +++ b/docs/guides/BUILDING.md @@ -57,7 +57,7 @@ sudo apt-get install git gcc g++ pkg-config libssl-dev libdbus-1-dev \ #### UI builds -If building `-with-ui` variant, also install SDL2: +If building via `build_examples.py` and `-with-ui` variant, also install SDL2: ``` sudo apt-get install libsdl2-dev @@ -251,6 +251,56 @@ ninja -C out/host src/inet/tests:tests_run > > This means that the tests passed in a previous build. +## Using `build_examples.py` + +The script `./scripts/build/build_examples.py` provides a uniform build +interface into using `gn`, `cmake`, `ninja` and other tools as needed to compile +various platforms. + +Use `./scripts/build/build_examples.py targets` to see a list of supported +targets. + +Example build commands: + +``` +# Compiles and runs all tests on the host: +./scripts/build/build_examples.py --target linux-x64-tests build + +# Compiles fuzzing tagets using libfuzzer (fuzzing requires clang) +./scripts/build/build_examples.py --target linux-x64-tests-clang-asan-libfuzzer build + +# Compiles a esp32 example +./scripts/build/build_examples.py --target esp32-m5stack-all-clusters build + +# Compiles a nrf example +./scripts/build/build_examples.py --target nrf-nrf5340dk-pump build +``` + +### `libfuzzer` unit tests + +`libfuzzer` unit tests tests are only compiled but not executed (you have to +manually execute them). For best error detection, some form of sanitizer like +`asan` should be used. + +To compile, use: + +``` +./scripts/build/build_examples.py --target linux-x64-tests-clang-asan-libfuzzer build +``` + +After which tests should be located in +`out/linux-x64-tests-clang-asan-libfuzzer/tests/`. + +#### `ossfuzz` configurations + +`ossfuzz` configurations are not stand-alone fuzzing and instead serve as an +integration point with external fuzzing automated builds. + +They pick up environment variables such as `$CFLAGS`, `$CXXFLAGS` and +`$LIB_FUZZING_ENGINE`. + +You likely want `libfuzzer` + `asan` builds instead for local testing. + ## Build custom configuration The build is configured by setting build arguments. These you can set in one of diff --git a/scripts/build/build/targets.py b/scripts/build/build/targets.py index afeff7ef8a2b73..49a6d74cbd2f43 100755 --- a/scripts/build/build/targets.py +++ b/scripts/build/build/targets.py @@ -21,7 +21,7 @@ from builders.efr32 import Efr32App, Efr32Board, Efr32Builder from builders.esp32 import Esp32App, Esp32Board, Esp32Builder from builders.genio import GenioApp, GenioBuilder -from builders.host import HostApp, HostBoard, HostBuilder, HostCryptoLibrary +from builders.host import HostApp, HostBoard, HostBuilder, HostCryptoLibrary, HostFuzzingType from builders.imx import IMXApp, IMXBuilder from builders.infineon import InfineonApp, InfineonBoard, InfineonBuilder from builders.k32w import K32WApp, K32WBuilder @@ -68,7 +68,8 @@ def BuildHostFakeTarget(): target.AppendModifier("asan", use_asan=True).ExceptIfRe("-tsan") target.AppendModifier("tsan", use_tsan=True).ExceptIfRe("-asan") target.AppendModifier("ubsan", use_ubsan=True) - target.AppendModifier("libfuzzer", use_libfuzzer=True).OnlyIfRe("-clang") + target.AppendModifier("libfuzzer", fuzzing_type=HostFuzzingType.LIB_FUZZER).OnlyIfRe("-clang").ExceptIfRe('-ossfuzz') + target.AppendModifier("ossfuzz", fuzzing_type=HostFuzzingType.OSS_FUZZ).OnlyIfRe("-clang").ExceptIfRe('-libfuzzer') target.AppendModifier('coverage', use_coverage=True).OnlyIfRe('-(chip-tool|all-clusters)') target.AppendModifier('dmalloc', use_dmalloc=True) target.AppendModifier('clang', use_clang=True) @@ -140,7 +141,8 @@ def BuildHostTarget(): target.AppendModifier("asan", use_asan=True).ExceptIfRe("-tsan") target.AppendModifier("tsan", use_tsan=True).ExceptIfRe("-asan") target.AppendModifier("ubsan", use_ubsan=True) - target.AppendModifier("libfuzzer", use_libfuzzer=True).OnlyIfRe("-clang") + target.AppendModifier("libfuzzer", fuzzing_type=HostFuzzingType.LIB_FUZZER).OnlyIfRe("-clang").ExceptIfRe('-ossfuzz') + target.AppendModifier("ossfuzz", fuzzing_type=HostFuzzingType.OSS_FUZZ).OnlyIfRe("-clang").ExceptIfRe('-libfuzzer') target.AppendModifier('coverage', use_coverage=True).OnlyIfRe('-(chip-tool|all-clusters)') target.AppendModifier('dmalloc', use_dmalloc=True) target.AppendModifier('clang', use_clang=True) diff --git a/scripts/build/builders/host.py b/scripts/build/builders/host.py index 91fa10d0c36693..4ee845ea7fd969 100644 --- a/scripts/build/builders/host.py +++ b/scripts/build/builders/host.py @@ -35,6 +35,13 @@ def gn_argument(self): return 'chip_crypto="boringssl"' +class HostFuzzingType(Enum): + """Defines fuzz target options available for host targets.""" + NONE = auto() + LIB_FUZZER = auto() + OSS_FUZZ = auto() + + class HostApp(Enum): ALL_CLUSTERS = auto() ALL_CLUSTERS_MINIMAL = auto() @@ -239,14 +246,10 @@ class HostBuilder(GnBuilder): def __init__(self, root, runner, app: HostApp, board=HostBoard.NATIVE, enable_ipv4=True, enable_ble=True, enable_wifi=True, enable_thread=True, use_tsan=False, use_asan=False, use_ubsan=False, - separate_event_loop=True, use_libfuzzer=False, use_clang=False, - interactive_mode=True, extra_tests=False, - use_platform_mdns=False, enable_rpcs=False, - use_coverage=False, use_dmalloc=False, - minmdns_address_policy=None, - minmdns_high_verbosity=False, - imgui_ui=False, - crypto_library: HostCryptoLibrary = None): + separate_event_loop=True, fuzzing_type: HostFuzzingType = HostFuzzingType.NONE, use_clang=False, + interactive_mode=True, extra_tests=False, use_platform_mdns=False, enable_rpcs=False, + use_coverage=False, use_dmalloc=False, minmdns_address_policy=None, + minmdns_high_verbosity=False, imgui_ui=False, crypto_library: HostCryptoLibrary = None): super(HostBuilder, self).__init__( root=os.path.join(root, 'examples', app.ExamplePath()), runner=runner) @@ -296,8 +299,10 @@ def __init__(self, root, runner, app: HostApp, board=HostBoard.NATIVE, if not interactive_mode: self.extra_gn_options.append('config_use_interactive_mode=false') - if use_libfuzzer: + if fuzzing_type == HostFuzzingType.LIB_FUZZER: self.extra_gn_options.append('is_libfuzzer=true') + elif fuzzing_type == HostFuzzingType.OSS_FUZZ: + self.extra_gn_options.append('oss_fuzz=true') if imgui_ui: self.extra_gn_options.append('chip_examples_enable_imgui_ui=true') @@ -367,6 +372,9 @@ def __init__(self, root, runner, app: HostApp, board=HostBoard.NATIVE, if self.app == HostApp.SIMULATED_APP2: self.extra_gn_options.append('chip_tests_zap_config="app2"') + if self.app == HostApp.TESTS and fuzzing_type != HostFuzzingType.NONE: + self.build_command = 'fuzz_tests' + def GnBuildArgs(self): if self.board == HostBoard.NATIVE: return self.extra_gn_options diff --git a/scripts/build/testdata/all_targets_linux_x64.txt b/scripts/build/testdata/all_targets_linux_x64.txt index b117fe363a994d..63ad58f917a54a 100644 --- a/scripts/build/testdata/all_targets_linux_x64.txt +++ b/scripts/build/testdata/all_targets_linux_x64.txt @@ -7,8 +7,8 @@ cyw30739-cyw930739m2evb_01-{light,lock,ota-requestor,switch} efr32-{brd4161a,brd4187c,brd4186c,brd4163a,brd4164a,brd4166a,brd4170a,brd4186a,brd4187a,brd4304a}-{window-covering,switch,unit-test,light,lock,thermostat}[-rpc][-with-ota-requestor][-sed][-low-power][-shell][-no_logging][-openthread_mtd][-enable_heap_monitoring][-no_openthread_cli][-show_qr_code][-wifi][-rs911x][-wf200][-wifi_ipv4][-additional_data_advertising][-use_ot_lib][-use_ot_coap_lib][-no-version] esp32-{m5stack,c3devkit,devkitc,qemu}-{all-clusters,all-clusters-minimal,ota-provider,ota-requestor,shell,light,lock,bridge,temperature-measurement,ota-requestor,tests}[-rpc][-ipv6only] genio-lighting-app -linux-fake-tests[-mbedtls][-boringssl][-asan][-tsan][-ubsan][-libfuzzer][-coverage][-dmalloc][-clang] -linux-{x64,arm64}-{rpc-console,all-clusters,all-clusters-minimal,chip-tool,thermostat,java-matter-controller,minmdns,light,lock,shell,ota-provider,ota-requestor,simulated-app1,simulated-app2,python-bindings,tv-app,tv-casting-app,bridge,dynamic-bridge,tests,chip-cert,address-resolve-tool,contact-sensor}[-nodeps][-platform-mdns][-minmdns-verbose][-libnl][-same-event-loop][-no-interactive][-ipv6only][-no-ble][-no-wifi][-no-thread][-mbedtls][-boringssl][-asan][-tsan][-ubsan][-libfuzzer][-coverage][-dmalloc][-clang][-test][-rpc][-with-ui] +linux-fake-tests[-mbedtls][-boringssl][-asan][-tsan][-ubsan][-libfuzzer][-ossfuzz][-coverage][-dmalloc][-clang] +linux-{x64,arm64}-{rpc-console,all-clusters,all-clusters-minimal,chip-tool,thermostat,java-matter-controller,minmdns,light,lock,shell,ota-provider,ota-requestor,simulated-app1,simulated-app2,python-bindings,tv-app,tv-casting-app,bridge,dynamic-bridge,tests,chip-cert,address-resolve-tool,contact-sensor}[-nodeps][-platform-mdns][-minmdns-verbose][-libnl][-same-event-loop][-no-interactive][-ipv6only][-no-ble][-no-wifi][-no-thread][-mbedtls][-boringssl][-asan][-tsan][-ubsan][-libfuzzer][-ossfuzz][-coverage][-dmalloc][-clang][-test][-rpc][-with-ui] linux-x64-efr32-test-runner[-clang] imx-{chip-tool,lighting-app,thermostat,all-clusters-app,all-clusters-minimal-app,ota-provider-app}[-release] infineon-psoc6-{lock,light,all-clusters,all-clusters-minimal}[-ota][-updateimage]