-
-
Notifications
You must be signed in to change notification settings - Fork 2.8k
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
base: master
Are you sure you want to change the base?
Conversation
.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); | ||
} | ||
}, |
There was a problem hiding this comment.
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:
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:
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.
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.
9d6b20f
to
a8d5b75
Compare
-fsanitize-c=trap|full
in addition to the existing form.-f(no-)sanitize-trap=undefined
inzig cc
.std.Build.Module.sanitize_c
tostd.zig.SanitizeC
.Compilation.Config
fields to the cache.Closes #23216.