From 3a5a2f8204fcd10f71343a0cc5f4320654deca30 Mon Sep 17 00:00:00 2001 From: Chris Allen Date: Sat, 27 Dec 2025 13:44:28 -0600 Subject: [PATCH] fuzzers --- .gitignore | 1 + flake.nix | 163 ++++++++++++++++++++++++++++++++++++++++++++++------- 2 files changed, 143 insertions(+), 21 deletions(-) diff --git a/.gitignore b/.gitignore index ea2cd7ba..f626a59b 100644 --- a/.gitignore +++ b/.gitignore @@ -89,3 +89,4 @@ subprojects/* Irssi-Dist setup.cfg *.egg-info +result diff --git a/flake.nix b/flake.nix index a616b077..93edcc41 100644 --- a/flake.nix +++ b/flake.nix @@ -29,6 +29,72 @@ perl ]; + # Build fuzzers with clang and libfuzzer + # sanitizers: list of sanitizers to enable (e.g., ["address" "undefined"]) + mkFuzzerPackage = { sanitizers ? [ "address" "undefined" ] }: + let + # Use clang's stdenv for libfuzzer support + clangStdenv = pkgs.llvmPackages.stdenv; + + # Build sanitizer flags for linking (includes fuzzer) + sanitizerFlags = pkgs.lib.concatMapStringsSep "," (s: s) sanitizers; + fullSanitizerFlags = + if sanitizers == [] then "-fsanitize=fuzzer" + else "-fsanitize=fuzzer,${sanitizerFlags}"; + + # Compile-time sanitizer flags (without fuzzer - meson adds fuzzer-no-link) + compileSanitizerFlags = + if sanitizers == [] then "" + else "-fsanitize=${sanitizerFlags}"; + in + clangStdenv.mkDerivation { + pname = "irssi-fuzz"; + version = "1.5-head"; + + src = ./.; + + nativeBuildInputs = with pkgs; [ + meson + ninja + pkg-config + perl # Needed at build time for generating help files + ]; + + buildInputs = with pkgs; [ + glib + openssl + ncurses + ]; + + # Use preConfigure to set CFLAGS/LDFLAGS since meson's -Dc_args + # breaks the initial compiler test when sanitizers are involved + preConfigure = pkgs.lib.optionalString (sanitizers != []) '' + export CFLAGS="-g -O1 -fno-omit-frame-pointer ${compileSanitizerFlags}" + export LDFLAGS="${compileSanitizerFlags}" + ''; + + mesonFlags = [ + "-Dwith-perl=no" + "-Dwithout-textui=yes" + "-Dwith-fuzzer=yes" + "-Dwith-fuzzer-lib=${fullSanitizerFlags}" + "-Dfuzzer-link-language=c" + ]; + + # Only install the fuzzer binaries + postInstall = '' + # Remove non-fuzzer files if any were installed + rm -rf $out/share $out/include $out/lib/pkgconfig || true + ''; + + meta = with pkgs.lib; { + description = "Irssi fuzz testing targets built with libFuzzer"; + homepage = "https://irssi.org/"; + license = licenses.gpl2Plus; + platforms = platforms.unix; + }; + }; + in { packages = { @@ -87,32 +153,87 @@ platforms = platforms.unix; }; }; + + # Fuzzers with AddressSanitizer + UndefinedBehaviorSanitizer (recommended) + fuzz = mkFuzzerPackage { + sanitizers = [ "address" "undefined" ]; + }; + + # Fuzzers with only AddressSanitizer (faster, catches memory errors) + fuzz-asan = mkFuzzerPackage { + sanitizers = [ "address" ]; + }; + + # Fuzzers with only UndefinedBehaviorSanitizer + fuzz-ubsan = mkFuzzerPackage { + sanitizers = [ "undefined" ]; + }; }; - devShells.default = pkgs.mkShell { - name = "irssi-dev"; + devShells = { + default = pkgs.mkShell { + name = "irssi-dev"; - inherit buildInputs; + inherit buildInputs; - nativeBuildInputs = nativeBuildInputs ++ (with pkgs; [ - # Additional development tools - gdb - valgrind - ] ++ pkgs.lib.optionals pkgs.stdenv.isLinux [ - strace - ]); + nativeBuildInputs = nativeBuildInputs ++ (with pkgs; [ + # Additional development tools + gdb + valgrind + ] ++ pkgs.lib.optionals pkgs.stdenv.isLinux [ + strace + ]); - shellHook = '' - echo "Irssi development environment" - echo "" - echo "Build commands:" - echo " meson setup Build" - echo " ninja -C Build" - echo "" - echo "Run tests:" - echo " ninja -C Build test" - echo "" - ''; + shellHook = '' + echo "Irssi development environment" + echo "" + echo "Build commands:" + echo " meson setup Build" + echo " ninja -C Build" + echo "" + echo "Run tests:" + echo " ninja -C Build test" + echo "" + ''; + }; + + # Development shell for fuzzing + fuzz = pkgs.mkShell.override { stdenv = pkgs.llvmPackages.stdenv; } { + name = "irssi-fuzz-dev"; + + buildInputs = with pkgs; [ + glib + openssl + ncurses + ]; + + nativeBuildInputs = with pkgs; [ + meson + ninja + pkg-config + perl + # Fuzzing tools + llvmPackages.llvm # For llvm-symbolizer, llvm-cov, etc. + ]; + + shellHook = '' + echo "Irssi fuzzing development environment (clang + libFuzzer)" + echo "" + echo "Build fuzzers:" + echo " meson setup Build-fuzz -Dwith-perl=no -Dwithout-textui=yes -Dwith-fuzzer=yes" + echo " ninja -C Build-fuzz" + echo "" + echo "Fuzz targets will be in Build-fuzz/src/fe-fuzz/:" + echo " - irssi-fuzz" + echo " - server-fuzz" + echo " - event-get-params-fuzz (in irc/core/)" + echo " - theme-load-fuzz (in fe-common/core/)" + echo "" + echo "Run a fuzzer:" + echo " ./Build-fuzz/src/fe-fuzz/irssi-fuzz corpus/" + echo "" + ''; + }; }; } );