From b50c557e747119d5d95dd1b15e7d19fd09393095 Mon Sep 17 00:00:00 2001 From: Sergei Zimmerman <145775305+xokdvium@users.noreply.github.com> Date: Sat, 8 Mar 2025 21:08:35 +0000 Subject: [PATCH] flake: Enable UBSAN for checks Doing this makes catching non-obvious bugs easier. GHA CI workload is already a concern and there isn't much benefit in running the tests with and without sanitizers at the same time, so UBSAN is enabled for default checks. This change doesn't affect production builds in any way, but is rather a step in the direction of improving automated testing during development. Relates to #10969. (cherry picked from commit 874587516ca21b55ad03ae6fa2b5428b199452eb) --- flake.nix | 38 +++++++++++++++++++++++++++++++++----- src/libutil/strings.cc | 4 +++- 2 files changed, 36 insertions(+), 6 deletions(-) diff --git a/flake.nix b/flake.nix index 037281eb5..87f1350e0 100644 --- a/flake.nix +++ b/flake.nix @@ -267,18 +267,46 @@ flatMapAttrs ( { - "" = nixpkgsFor.${system}.native; + # Run all tests with UBSAN enabled. Running both with ubsan and + # without doesn't seem to have much immediate benefit for doubling + # the GHA CI workaround. + # + # TODO: Work toward enabling "address,undefined" if it seems feasible. + # This would maybe require dropping Boost coroutines and ignoring intentional + # memory leaks with detect_leaks=0. + "" = rec { + nixpkgs = nixpkgsFor.${system}.native; + nixComponents = nixpkgs.nixComponents.overrideScope ( + nixCompFinal: nixCompPrev: { + mesonComponentOverrides = _finalAttrs: prevAttrs: { + mesonFlags = + (prevAttrs.mesonFlags or [ ]) + # TODO: Macos builds instrumented with ubsan take very long + # to run functional tests. + ++ lib.optionals (!nixpkgs.stdenv.hostPlatform.isDarwin) [ + (lib.mesonOption "b_sanitize" "undefined") + ]; + }; + } + ); + }; } // lib.optionalAttrs (!nixpkgsFor.${system}.native.stdenv.hostPlatform.isDarwin) { # TODO: enable static builds for darwin, blocked on: # https://github.com/NixOS/nixpkgs/issues/320448 # TODO: disabled to speed up GHA CI. - #"static-" = nixpkgsFor.${system}.native.pkgsStatic; + # "static-" = { + # nixpkgs = nixpkgsFor.${system}.native.pkgsStatic; + # }; } ) ( - nixpkgsPrefix: nixpkgs: - flatMapAttrs nixpkgs.nixComponents ( + nixpkgsPrefix: + { + nixpkgs, + nixComponents ? nixpkgs.nixComponents, + }: + flatMapAttrs nixComponents ( pkgName: pkg: flatMapAttrs pkg.tests or { } ( testName: test: { @@ -287,7 +315,7 @@ ) ) // lib.optionalAttrs (nixpkgs.stdenv.hostPlatform == nixpkgs.stdenv.buildPlatform) { - "${nixpkgsPrefix}nix-functional-tests" = nixpkgs.nixComponents.nix-functional-tests; + "${nixpkgsPrefix}nix-functional-tests" = nixComponents.nix-functional-tests; } ) // devFlake.checks.${system} or { } diff --git a/src/libutil/strings.cc b/src/libutil/strings.cc index b94bca611..1635321bb 100644 --- a/src/libutil/strings.cc +++ b/src/libutil/strings.cc @@ -17,8 +17,10 @@ struct view_stringbuf : public std::stringbuf } }; -std::string_view toView(const std::ostringstream & os) +__attribute__((no_sanitize("undefined"))) std::string_view toView(const std::ostringstream & os) { + /* Downcasting like this is very much undefined behavior, so we disable + UBSAN for this function. */ auto buf = static_cast(os.rdbuf()); return buf->toView(); }