libpldm: Add fuzzing for firmware FD responder
This includes a fuzz target fd-fuzz, and infrastructure to run with
either honggfuzz or AFL.
fd-fuzz-input1.dat was crafted from parts of a pldm firmware update
packet capture, as a seed to guide fuzzers.
Signed-off-by: Matt Johnston <matt@codeconstruct.com.au>
Change-Id: I424761a29a22bc964201fd7bd94ddc09a6ac89df
diff --git a/tests/fuzz/fuzz-build.py b/tests/fuzz/fuzz-build.py
new file mode 100755
index 0000000..cc34fb7
--- /dev/null
+++ b/tests/fuzz/fuzz-build.py
@@ -0,0 +1,90 @@
+#!/usr/bin/env python3
+# SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
+
+# Builds fuzzing variants. Run this from the toplevel directory.
+# Beware this will wipe build directories.
+
+# Requires honggfuzz and afl++ installed
+
+# Builds are:
+# * AFL (normal, asan, cmplog)
+# * honggfuzz
+# * -O0, with coverage
+
+import os
+import subprocess
+
+# reduce warning level since tests since gtest is noisy
+BASE_MESONFLAGS = "-Dwarning_level=2 -Ddefault_library=static --wipe".split()
+FUZZ_PROGRAMS = ["tests/fuzz/fd-fuzz"]
+
+
+def build(
+ build_dir: str,
+ cc: str = None,
+ cxx: str = None,
+ cflags="",
+ cxxflags="",
+ opt="3",
+ env={},
+ mesonflags=[],
+):
+ env = os.environ | env
+ env["CFLAGS"] = cflags
+ env["CXXFLAGS"] = cxxflags
+
+ # Meson sets CC="ccache cc" by default, but ccache removes -fprofile-arcs
+ # so coverage breaks (ccache #1531). Prevent that by setting CC/CXX.
+ env["CC"] = cc if cc else "cc"
+ env["CXX"] = cxx if cxx else "c++"
+
+ meson_cmd = ["meson"] + BASE_MESONFLAGS + mesonflags
+ meson_cmd += [f"-Doptimization={opt}"]
+ meson_cmd += [build_dir]
+ subprocess.run(meson_cmd, env=env, check=True)
+
+ ninja_cmd = ["ninja", "-C", build_dir] + FUZZ_PROGRAMS
+ subprocess.run(ninja_cmd, env=env, check=True)
+
+
+def build_afl():
+ env = {
+ # seems to be required for afl-clang-lto?
+ "AFL_REAL_LD": "ld.lld",
+ }
+ cc = "afl-clang-lto"
+ cxx = "afl-clang-lto++"
+
+ # normal
+ build("bfuzz", cc=cc, cxx=cxx, env=env)
+ # ASAN
+ build(
+ "bfuzzasan",
+ cc=cc,
+ cxx=cxx,
+ mesonflags=["-Db_sanitize=address"],
+ env=env,
+ )
+ # cmplog
+ build("bcmplog", cc=cc, cxx=cxx, env={"AFL_LLVM_CMPLOG": "1"} | env)
+
+
+def main():
+ # No profiling, has coverage
+ build(
+ "bnoopt",
+ cflags="-fprofile-abs-path",
+ cxxflags="-fprofile-abs-path",
+ opt="0",
+ mesonflags=["-Db_coverage=true"],
+ )
+
+ # AFL
+ build_afl()
+
+ # Honggfuzz
+ build("bhf", cc="hfuzz-clang", cxx="hfuzz-clang++")
+
+
+if __name__ == "__main__":
+ main()