From a10854654d47e43c5a8240cdbbe8cebac7195b07 Mon Sep 17 00:00:00 2001 From: Alessandro De Blasis Date: Fri, 10 Apr 2026 08:46:23 +0200 Subject: [PATCH] build: disable ubsan in C deps for MSVC static linking Zig's ubsan runtime cannot be bundled on Windows (LNK4229), leaving __ubsan_handle_* symbols unresolved when the static archive is consumed by an external linker like MSVC link.exe. freetype, glslang, spirv-cross, and highway already suppress ubsan unconditionally. Add MSVC-conditional suppression to the seven C dependencies that were missing it: harfbuzz, libpng, dcimgui, wuffs, oniguruma, zlib, and stb. The fix is gated on abi == .msvc so ubsan coverage is preserved on Linux and macOS where bundle_ubsan_rt works. --- pkg/dcimgui/build.zig | 6 ++++++ pkg/harfbuzz/build.zig | 9 +++++++++ pkg/libpng/build.zig | 6 ++++++ pkg/oniguruma/build.zig | 6 ++++++ pkg/wuffs/build.zig | 4 ++++ pkg/zlib/build.zig | 6 ++++++ src/build/SharedDeps.zig | 11 ++++++++++- 7 files changed, 47 insertions(+), 1 deletion(-) diff --git a/pkg/dcimgui/build.zig b/pkg/dcimgui/build.zig index 01a5879d6..924e7c932 100644 --- a/pkg/dcimgui/build.zig +++ b/pkg/dcimgui/build.zig @@ -60,6 +60,12 @@ pub fn build(b: *std.Build) !void { "-DIMGUI_USE_WCHAR32=1", "-DIMGUI_DISABLE_OBSOLETE_FUNCTIONS=1", }); + if (target.result.abi == .msvc) { + try flags.appendSlice(b.allocator, &.{ + "-fno-sanitize=undefined", + "-fno-sanitize-trap=undefined", + }); + } if (freetype) try flags.appendSlice(b.allocator, &.{ "-DIMGUI_ENABLE_FREETYPE=1", }); diff --git a/pkg/harfbuzz/build.zig b/pkg/harfbuzz/build.zig index 6d8f3be70..b482bc8a3 100644 --- a/pkg/harfbuzz/build.zig +++ b/pkg/harfbuzz/build.zig @@ -123,6 +123,15 @@ fn buildLib(b: *std.Build, module: *std.Build.Module, options: anytype) !*std.Bu try flags.appendSlice(b.allocator, &.{ "-DHAVE_STDBOOL_H", }); + // Disable ubsan for MSVC: Zig's ubsan runtime cannot be bundled + // on Windows (LNK4229), leaving __ubsan_handle_* unresolved when + // the static archive is consumed by an external linker. + if (target.result.abi == .msvc) { + try flags.appendSlice(b.allocator, &.{ + "-fno-sanitize=undefined", + "-fno-sanitize-trap=undefined", + }); + } if (target.result.os.tag != .windows) { try flags.appendSlice(b.allocator, &.{ "-DHAVE_UNISTD_H", diff --git a/pkg/libpng/build.zig b/pkg/libpng/build.zig index dbedac632..8734b28f9 100644 --- a/pkg/libpng/build.zig +++ b/pkg/libpng/build.zig @@ -54,6 +54,12 @@ pub fn build(b: *std.Build) !void { "-DPNG_INTEL_SSE_OPT=0", "-DPNG_MIPS_MSA_OPT=0", }); + if (target.result.abi == .msvc) { + try flags.appendSlice(b.allocator, &.{ + "-fno-sanitize=undefined", + "-fno-sanitize-trap=undefined", + }); + } lib.addCSourceFiles(.{ .root = upstream.path(""), diff --git a/pkg/oniguruma/build.zig b/pkg/oniguruma/build.zig index efc013b43..d142e5eb1 100644 --- a/pkg/oniguruma/build.zig +++ b/pkg/oniguruma/build.zig @@ -103,6 +103,12 @@ fn buildLib(b: *std.Build, module: *std.Build.Module, options: anytype) !*std.Bu var flags: std.ArrayList([]const u8) = .empty; defer flags.deinit(b.allocator); + if (target.result.abi == .msvc) { + try flags.appendSlice(b.allocator, &.{ + "-fno-sanitize=undefined", + "-fno-sanitize-trap=undefined", + }); + } lib.addCSourceFiles(.{ .root = upstream.path(""), .flags = flags.items, diff --git a/pkg/wuffs/build.zig b/pkg/wuffs/build.zig index 3d9f83daa..95cef3e09 100644 --- a/pkg/wuffs/build.zig +++ b/pkg/wuffs/build.zig @@ -20,6 +20,10 @@ pub fn build(b: *std.Build) !void { var flags: std.ArrayList([]const u8) = .empty; defer flags.deinit(b.allocator); try flags.append(b.allocator, "-DWUFFS_IMPLEMENTATION"); + if (target.result.abi == .msvc) { + try flags.append(b.allocator, "-fno-sanitize=undefined"); + try flags.append(b.allocator, "-fno-sanitize-trap=undefined"); + } inline for (@import("src/c.zig").defines) |key| { try flags.append(b.allocator, "-D" ++ key); } diff --git a/pkg/zlib/build.zig b/pkg/zlib/build.zig index 6bde60ec7..64db13aa1 100644 --- a/pkg/zlib/build.zig +++ b/pkg/zlib/build.zig @@ -33,6 +33,12 @@ pub fn build(b: *std.Build) !void { "-DHAVE_STDINT_H", "-DHAVE_STDDEF_H", }); + if (target.result.abi == .msvc) { + try flags.appendSlice(b.allocator, &.{ + "-fno-sanitize=undefined", + "-fno-sanitize-trap=undefined", + }); + } if (target.result.os.tag != .windows) { try flags.append(b.allocator, "-DZ_HAVE_UNISTD_H"); } diff --git a/src/build/SharedDeps.zig b/src/build/SharedDeps.zig index 5ca5368d7..b68be92d0 100644 --- a/src/build/SharedDeps.zig +++ b/src/build/SharedDeps.zig @@ -412,7 +412,16 @@ pub fn add( // C files step.linkLibC(); step.addIncludePath(b.path("src/stb")); - step.addCSourceFiles(.{ .files = &.{"src/stb/stb.c"} }); + // Disable ubsan for MSVC: Zig's ubsan runtime cannot be bundled + // on Windows (LNK4229), leaving __ubsan_handle_* unresolved when + // the static archive is consumed by an external linker. + step.addCSourceFiles(.{ + .files = &.{"src/stb/stb.c"}, + .flags = if (step.rootModuleTarget().abi == .msvc) + &.{ "-fno-sanitize=undefined", "-fno-sanitize-trap=undefined" } + else + &.{}, + }); if (step.rootModuleTarget().os.tag == .linux) { step.addIncludePath(b.path("src/apprt/gtk")); }