| Matt Johnston | 060c71e | 2025-01-08 14:35:13 +0800 | [diff] [blame] | 1 | #!/usr/bin/env python3 | 
|  | 2 | # SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later | 
|  | 3 |  | 
|  | 4 | # Builds fuzzing variants. Run this from the toplevel directory. | 
|  | 5 | # Beware this will wipe build directories. | 
|  | 6 |  | 
|  | 7 | # Requires honggfuzz and afl++ installed | 
|  | 8 |  | 
|  | 9 | # Builds are: | 
|  | 10 | # * AFL (normal, asan, cmplog) | 
|  | 11 | # * honggfuzz (asan, msan, ubsan) | 
|  | 12 | # * -O0, with coverage | 
|  | 13 |  | 
|  | 14 | import os | 
|  | 15 | import subprocess | 
|  | 16 |  | 
|  | 17 | # reduce warning level since tests since gtest is noisy | 
|  | 18 | BASE_MESONFLAGS = "-Dwarning_level=2 -Ddefault_library=static --wipe".split() | 
|  | 19 | FUZZ_PROGRAMS = ["tests/fuzz/i2c-fuzz"] | 
|  | 20 |  | 
|  | 21 |  | 
|  | 22 | def build( | 
|  | 23 | build_dir: str, | 
|  | 24 | cc: str = None, | 
|  | 25 | cxx: str = None, | 
|  | 26 | cflags="", | 
|  | 27 | cxxflags="", | 
|  | 28 | opt="3", | 
|  | 29 | env={}, | 
|  | 30 | mesonflags=[], | 
|  | 31 | ): | 
|  | 32 | env = os.environ | env | 
|  | 33 | env["CFLAGS"] = cflags | 
|  | 34 | env["CXXFLAGS"] = cxxflags | 
|  | 35 |  | 
|  | 36 | # Meson sets CC="ccache cc" by default, but ccache removes -fprofile-arcs | 
|  | 37 | # so coverage breaks (ccache #1531). Prevent that by setting CC/CXX. | 
|  | 38 | env["CC"] = cc if cc else "cc" | 
|  | 39 | env["CXX"] = cxx if cxx else "c++" | 
|  | 40 |  | 
|  | 41 | meson_cmd = ["meson"] + BASE_MESONFLAGS + mesonflags | 
|  | 42 | meson_cmd += [f"-Doptimization={opt}"] | 
|  | 43 | meson_cmd += [build_dir] | 
|  | 44 | subprocess.run(meson_cmd, env=env, check=True) | 
|  | 45 |  | 
|  | 46 | ninja_cmd = ["ninja", "-C", build_dir] + FUZZ_PROGRAMS | 
|  | 47 | subprocess.run(ninja_cmd, env=env, check=True) | 
|  | 48 |  | 
|  | 49 |  | 
|  | 50 | def build_afl(): | 
|  | 51 | env = { | 
|  | 52 | # seems to be required for afl-clang-lto? | 
|  | 53 | "AFL_REAL_LD": "ld.lld", | 
|  | 54 | } | 
|  | 55 | cc = "afl-clang-lto" | 
|  | 56 | cxx = "afl-clang-lto++" | 
|  | 57 |  | 
|  | 58 | # normal | 
|  | 59 | build("bfuzz", cc=cc, cxx=cxx, env=env) | 
|  | 60 | # ASAN | 
|  | 61 | build( | 
|  | 62 | "bfuzzasan", | 
|  | 63 | cc=cc, | 
|  | 64 | cxx=cxx, | 
|  | 65 | mesonflags=["-Db_sanitize=address"], | 
|  | 66 | env=env, | 
|  | 67 | ) | 
|  | 68 | # cmplog | 
|  | 69 | build("bcmplog", cc=cc, cxx=cxx, env={"AFL_LLVM_CMPLOG": "1"} | env) | 
|  | 70 |  | 
|  | 71 |  | 
|  | 72 | def main(): | 
|  | 73 | # No profiling, has coverage | 
|  | 74 | build( | 
|  | 75 | "bnoopt", | 
|  | 76 | cflags="-fprofile-abs-path", | 
|  | 77 | cxxflags="-fprofile-abs-path", | 
|  | 78 | opt="0", | 
|  | 79 | mesonflags=["-Db_coverage=true"], | 
|  | 80 | ) | 
|  | 81 |  | 
|  | 82 | # AFL | 
|  | 83 | build_afl() | 
|  | 84 |  | 
|  | 85 | # Honggfuzz | 
|  | 86 | # asan by default | 
|  | 87 | build( | 
|  | 88 | "bhf", | 
|  | 89 | cc="hfuzz-clang", | 
|  | 90 | cxx="hfuzz-clang++", | 
|  | 91 | env={"HFUZZ_CC_ASAN": "1"}, | 
|  | 92 | ) | 
|  | 93 | # msan | 
|  | 94 | build( | 
|  | 95 | "bhf-msan", | 
|  | 96 | cc="hfuzz-clang", | 
|  | 97 | cxx="hfuzz-clang++", | 
|  | 98 | env={"HFUZZ_CC_MSAN": "1"}, | 
|  | 99 | ) | 
|  | 100 | # ubsan | 
|  | 101 | build( | 
|  | 102 | "bhf-ubsan", | 
|  | 103 | cc="hfuzz-clang", | 
|  | 104 | cxx="hfuzz-clang++", | 
|  | 105 | env={"HFUZZ_CC_UBSAN": "1"}, | 
|  | 106 | ) | 
|  | 107 |  | 
|  | 108 |  | 
|  | 109 | if __name__ == "__main__": | 
|  | 110 | main() |