Skip to content
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

compiler_rt: Port UBSan mini-runtime #5165

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions lib/std/special/compiler_rt.zig
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ comptime {
// __clear_cache manages its own logic about whether to be exported or not.
_ = @import("compiler_rt/clear_cache.zig").clear_cache;

_ = @import("compiler_rt/ubsan.zig");

@export(@import("compiler_rt/compareXf2.zig").__lesf2, .{ .name = "__lesf2", .linkage = linkage });
@export(@import("compiler_rt/compareXf2.zig").__ledf2, .{ .name = "__ledf2", .linkage = linkage });
@export(@import("compiler_rt/compareXf2.zig").__letf2, .{ .name = "__letf2", .linkage = linkage });
Expand Down
66 changes: 66 additions & 0 deletions lib/std/special/compiler_rt/ubsan.zig
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
// Mini runtime support for Clang's Undefined Behavior sanitizer
const std = @import("std");
const builtin = std.builtin;

// Creates two handlers for a given error, both of them print the specified
// return message but the `abort_` version stops the execution of the program
// XXX: Don't depend on the stdlib
fn makeHandler(comptime error_msg: []const u8) type {
return struct {
pub fn recover_handler() callconv(.C) void {
const PC = @returnAddress() -% 1;
std.debug.warn("ubsan: " ++ error_msg ++ " @ 0x{x}\n", .{PC});
}
pub fn abort_handler() callconv(.C) noreturn {
const PC = @returnAddress() -% 1;
std.debug.panic("ubsan: " ++ error_msg ++ " @ 0x{x}\n", .{PC});
}
};
}

comptime {
const HANDLERS = .{
.{ "type_mismatch", "type-mismatch", .Both },
.{ "alignment_assumption", "alignment-assumption", .Both },
.{ "add_overflow", "add-overflow", .Both },
.{ "sub_overflow", "sub-overflow", .Both },
.{ "mul_overflow", "mul-overflow", .Both },
.{ "negate_overflow", "negate-overflow", .Both },
.{ "divrem_overflow", "divrem-overflow", .Both },
.{ "shift_out_of_bounds", "shift-out-of-bounds", .Both },
.{ "out_of_bounds", "out-of-bounds", .Both },
.{ "builtin_unreachable", "builtin-unreachable", .Recover },
.{ "missing_return", "missing-return", .Recover },
.{ "vla_bound_not_positive", "vla-bound-not-positive", .Both },
.{ "float_cast_overflow", "float-cast-overflow", .Both },
.{ "load_invalid_value", "load-invalid-value", .Both },
.{ "invalid_builtin", "invalid-builtin", .Both },
.{ "function_type_mismatch", "function-type-mismatch", .Both },
.{ "implicit_conversion", "implicit-conversion", .Both },
.{ "nonnull_arg", "nonnull-arg", .Both },
.{ "nonnull_return", "nonnull-return", .Both },
.{ "nullability_arg", "nullability-arg", .Both },
.{ "nullability_return", "nullability-return", .Both },
.{ "pointer_overflow", "pointer-overflow", .Both },
.{ "cfi_check_fail", "cfi-check-fail", .Both },
};

const linkage: builtin.GlobalLinkage = if (std.builtin.is_test) .Internal else .Weak;

inline for (HANDLERS) |entry| {
const S = makeHandler(entry[1]);

// The non-aborting variant is always needed
{
const N = "__ubsan_handle_" ++ entry[0] ++ "_minimal";
const O = std.builtin.ExportOptions{ .name = N, .linkage = linkage };
@export(S.recover_handler, O);
}

if (entry[2] == .Both) {
const N = "__ubsan_handle_" ++ entry[0] ++ "_minimal_abort";
const O = std.builtin.ExportOptions{ .name = N, .linkage = linkage };
@export(S.abort_handler, O);
}
}
}
2 changes: 1 addition & 1 deletion src/codegen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9412,7 +9412,7 @@ void add_cc_args(CodeGen *g, ZigList<const char *> &args, const char *out_dep_pa

if (g->have_sanitize_c) {
args.append("-fsanitize=undefined");
args.append("-fsanitize-trap=undefined");
args.append("-fsanitize-minimal-runtime");
}

switch (g->build_mode) {
Expand Down