Skip to content

compiler: Allow configuring UBSan mode at the module level. #23582

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

alexrp
Copy link
Member

@alexrp alexrp commented Apr 16, 2025

  • Accept -fsanitize-c=trap|full in addition to the existing form.
  • Accept -f(no-)sanitize-trap=undefined in zig cc.
  • Change type of std.Build.Module.sanitize_c to std.zig.SanitizeC.
  • Add some missing Compilation.Config fields to the cache.

Closes #23216.

Comment on lines +2254 to +2296
.sanitize_trap, .no_sanitize_trap => |t| {
const enable = t == .sanitize_trap;
var san_it = std.mem.splitScalar(u8, it.only_arg, ',');
var recognized_any = false;
while (san_it.next()) |sub_arg| {
// This logic doesn't match Clang 1:1, but it's probably good enough, and avoids
// significantly complicating the resolution of the options.
if (mem.eql(u8, sub_arg, "undefined")) {
if (mod_opts.sanitize_c) |sc| switch (sc) {
.off => if (enable) {
mod_opts.sanitize_c = .trap;
},
.trap => if (!enable) {
mod_opts.sanitize_c = .full;
},
.full => if (enable) {
mod_opts.sanitize_c = .trap;
},
} else {
if (enable) {
mod_opts.sanitize_c = .trap;
} else {
// This means we were passed `-fno-sanitize-trap=undefined` and nothing else. In
// this case, ideally, we should use whatever value `sanitize_c` resolves to by
// default, except change `trap` to `full`. However, we don't yet know what
// `sanitize_c` will resolve to! So we either have to pick `off` or `full`.
//
// `full` has the potential to be problematic if `optimize_mode` turns out to
// be `ReleaseFast`/`ReleaseSmall` because the user will get a slower and larger
// binary than expected. On the other hand, if `optimize_mode` turns out to be
// `Debug`/`ReleaseSafe`, `off` would mean UBSan would unexpectedly be disabled.
//
// `off` seems very slightly less bad, so let's go with that.
mod_opts.sanitize_c = .off;
}
}
recognized_any = true;
}
}
if (!recognized_any) {
try cc_argv.appendSlice(arena, it.other_args);
}
},
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I kind of hate this, but I'm not sure what to do about it.

I considered splitting sanitize_c into two fields: sanitize_c and sanitize_c_prefer_trap. But that just runs into the problem that we can't assign a meaningful value here:

zig/src/main.zig

Lines 2948 to 2954 in 9d6b20f

if (mod_opts.sanitize_c) |sc| switch (sc) {
.off => {},
.trap => if (create_module.opts.any_sanitize_c == .off) {
create_module.opts.any_sanitize_c = .trap;
},
.full => create_module.opts.any_sanitize_c = .full,
};

(Because the user might only have provided one or the other explicitly, and we need both to answer the question of whether any module in the compilation needs the UBSan runtime.)

It almost seems like iterating the full module graph here to determine whether the UBSan runtime is needed would be easier:

zig/src/Compilation.zig

Lines 1290 to 1297 in 9d6b20f

const any_sanitize_c: std.zig.SanitizeC = switch (options.config.any_sanitize_c) {
.off => options.root_mod.sanitize_c,
.trap => if (options.root_mod.sanitize_c == .full)
.full
else
.trap,
.full => .full,
};

Anyway, ideas welcome.

@alexrp
Copy link
Member Author

alexrp commented Apr 16, 2025

cc @Rexicon226

* Accept -fsanitize-c=trap|full in addition to the existing form.
* Accept -f(no-)sanitize-trap=undefined in zig cc.
* Change type of std.Build.Module.sanitize_c to std.zig.SanitizeC.
* Add some missing Compilation.Config fields to the cache.

Closes ziglang#23216.
@alexrp alexrp force-pushed the sanitize-c-trap-full branch from 9d6b20f to a8d5b75 Compare April 16, 2025 04:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

No option to have ubsan with trap instead of runtime
1 participant