Commit babee5f73c
Changed files (1)
lib
std
lib/std/ubsan.zig
@@ -140,7 +140,7 @@ fn overflowHandler(
data: *OverflowData,
lhs_handle: ValueHandle,
rhs_handle: ValueHandle,
- ) callconv(.C) noreturn {
+ ) callconv(.c) noreturn {
const lhs = lhs_handle.getValue(data);
const rhs = rhs_handle.getValue(data);
@@ -163,7 +163,7 @@ fn overflowHandler(
fn negationHandler(
data: *const OverflowData,
old_value_handle: ValueHandle,
-) callconv(.C) noreturn {
+) callconv(.c) noreturn {
const old_value = old_value_handle.getValue(data);
logMessage(
"negation of {} cannot be represented in type {s}",
@@ -175,7 +175,7 @@ fn divRemHandler(
data: *const OverflowData,
lhs_handle: ValueHandle,
rhs_handle: ValueHandle,
-) callconv(.C) noreturn {
+) callconv(.c) noreturn {
const is_signed = data.type_descriptor.isSigned();
const lhs = lhs_handle.getValue(data);
const rhs = rhs_handle.getValue(data);
@@ -199,7 +199,7 @@ fn alignmentAssumptionHandler(
pointer: ValueHandle,
alignment: ValueHandle,
maybe_offset: ?ValueHandle,
-) callconv(.C) noreturn {
+) callconv(.c) noreturn {
_ = pointer;
// TODO: add the hint here?
// const real_pointer = @intFromPtr(pointer) - @intFromPtr(maybe_offset);
@@ -233,7 +233,7 @@ fn shiftOob(
data: *const ShiftOobData,
lhs_handle: ValueHandle,
rhs_handle: ValueHandle,
-) callconv(.C) noreturn {
+) callconv(.c) noreturn {
const lhs: Value = .{ .handle = lhs_handle, .type_descriptor = data.lhs_type };
const rhs: Value = .{ .handle = rhs_handle, .type_descriptor = data.rhs_type };
@@ -266,7 +266,7 @@ const OutOfBoundsData = extern struct {
index_type: *const TypeDescriptor,
};
-fn outOfBounds(data: *const OutOfBoundsData, index_handle: ValueHandle) callconv(.C) noreturn {
+fn outOfBounds(data: *const OutOfBoundsData, index_handle: ValueHandle) callconv(.c) noreturn {
const index: Value = .{ .handle = index_handle, .type_descriptor = data.index_type };
logMessage(
"index {} out of bounds for type {s}",
@@ -282,7 +282,7 @@ fn pointerOverflow(
_: *const PointerOverflowData,
base: usize,
result: usize,
-) callconv(.C) noreturn {
+) callconv(.c) noreturn {
if (base == 0) {
if (result == 0) {
logMessage("applying zero offset to null pointer", .{});
@@ -318,12 +318,100 @@ const TypeMismatchData = extern struct {
upcast_to_virtual_base,
nonnull_assign,
dynamic_operation,
+
+ fn getName(kind: @This()) []const u8 {
+ return switch (kind) {
+ .load => "load of",
+ .store => "store of",
+ .reference_binding => "reference binding to",
+ .member_access => "member access within",
+ .member_call => "member call on",
+ .constructor_call => "constructor call on",
+ .downcast_pointer, .downcast_reference => "downcast of",
+ .upcast => "upcast of",
+ .upcast_to_virtual_base => "cast to virtual base of",
+ .nonnull_assign => "_Nonnull binding to",
+ .dynamic_operation => "dynamic operation on",
+ };
+ }
},
};
+fn typeMismatch(
+ data: *const TypeMismatchData,
+ pointer: ?ValueHandle,
+) callconv(.c) noreturn {
+ const alignment = @as(usize, 1) << @intCast(data.log_alignment);
+ const handle: usize = @intFromPtr(pointer);
+
+ if (pointer == null) {
+ logMessage(
+ "{s} null pointer of type {s}",
+ .{ data.kind.getName(), data.type_descriptor.getName() },
+ );
+ } else if (!std.mem.isAligned(handle, alignment)) {
+ logMessage(
+ "{s} misaligned address 0x{x} for type {s}, which requires {} byte alignment",
+ .{ data.kind.getName(), handle, data.type_descriptor.getName(), alignment },
+ );
+ } else {
+ logMessage(
+ "{s} address 0x{x} with insufficient space for an object of type {s}",
+ .{ data.kind.getName(), handle, data.type_descriptor.getName() },
+ );
+ }
+}
+
+const UnreachableData = extern struct {
+ loc: SourceLocation,
+};
+
+fn builtinUnreachable(_: *const UnreachableData) callconv(.c) noreturn {
+ logMessage("execution reached an unreachable program point", .{});
+}
+
+fn missingReturn(_: *const UnreachableData) callconv(.c) noreturn {
+ logMessage("execution reached the end of a value-returning function without returning a value", .{});
+}
+
+const NonNullReturnData = extern struct {
+ attribute_loc: SourceLocation,
+};
+
+fn nonNullReturn(_: *const NonNullReturnData) callconv(.c) noreturn {
+ logMessage("null pointer returned from function declared to never return null", .{});
+}
+
+const NonNullArgData = extern struct {
+ loc: SourceLocation,
+ attribute_loc: SourceLocation,
+ arg_index: i32,
+};
+
+fn nonNullArg(data: *const NonNullArgData) callconv(.c) noreturn {
+ logMessage(
+ "null pointer passed as argument {}, which is declared to never be null",
+ .{data.arg_index},
+ );
+}
+
+const InvalidValueData = extern struct {
+ loc: SourceLocation,
+ type_descriptor: *const TypeDescriptor,
+};
+
+fn loadInvalidValue(
+ data: *const InvalidValueData,
+ value_handle: ValueHandle,
+) callconv(.c) noreturn {
+ logMessage("load of value {}, which is not valid for type {s}", .{
+ value_handle.getValue(data), data.type_descriptor.getName(),
+ });
+}
+
fn SimpleHandler(comptime error_name: []const u8) type {
return struct {
- fn handler() callconv(.C) noreturn {
+ fn handler() callconv(.c) noreturn {
logMessage("{s}", .{error_name});
}
};
@@ -350,10 +438,11 @@ fn exportHandler(
}
fn exportMinimal(
- handler: anytype,
+ err_name: anytype,
comptime sym_name: []const u8,
comptime abort: bool,
) void {
+ const handler = &SimpleHandler(err_name).handler;
const linkage = if (builtin.is_test) .internal else .weak;
{
const N = "__ubsan_handle_" ++ sym_name ++ "_minimal";
@@ -371,7 +460,7 @@ fn exportHelper(
comptime abort: bool,
) void {
exportHandler(&SimpleHandler(err_name).handler, sym_name, abort);
- exportMinimal(&SimpleHandler(err_name).handler, sym_name, abort);
+ exportMinimal(err_name, sym_name, abort);
}
comptime {
@@ -384,35 +473,35 @@ comptime {
exportHandler(&shiftOob, "shift_out_of_bounds", true);
exportHandler(&outOfBounds, "out_of_bounds", true);
exportHandler(&pointerOverflow, "pointer_overflow", true);
+ exportHandler(&typeMismatch, "type_mismatch_v1", true);
+ exportHandler(&builtinUnreachable, "builtin_unreachable", false);
+ exportHandler(&missingReturn, "missing_return", false);
+ exportHandler(&nonNullReturn, "nonnull_return_v1", true);
+ exportHandler(&nonNullArg, "nonnull_arg", true);
+ exportHandler(&loadInvalidValue, "load_invalid_value", true);
- exportMinimal("add-overflow", "add_overflow", true);
- exportMinimal("sub-overflow", "sub_overflow", true);
- exportMinimal("mul-overflow", "mul_overflow", true);
- exportMinimal("negation-handler", "negate_overflow", true);
- exportMinimal("divrem-handler", "divrem_overflow", true);
- exportMinimal("alignment-assumption-handler", "alignment_assumption", true);
- exportMinimal("shift-oob", "shift_out_of_bounds", true);
- exportMinimal("out-of-bounds", "out_of_bounds", true);
- exportMinimal("pointer-overflow", "pointer_overflow", true);
-
- exportHandler(&SimpleHandler("type-mismatch-v1").handler, "type_mismatch_v1", true);
- exportMinimal(&SimpleHandler("type-mismatch").handler, "type_mismatch", true);
-
- exportHelper("builtin-unreachable", "builtin_unreachable", true);
- exportHelper("missing-return", "missing_return", false);
exportHelper("vla-bound-not-positive", "vla_bound_not_positive", true);
exportHelper("float-cast-overflow", "float_cast_overflow", true);
- exportHelper("load-invalid-value", "load_invalid_value", true);
exportHelper("invalid-builtin", "invalid_builtin", true);
exportHelper("function-type-mismatch", "function_type_mismatch", true);
exportHelper("implicit-conversion", "implicit_conversion", true);
- exportHelper("nonnull-arg", "nonnull_arg", true);
- exportHelper("nonnull-return", "nonnull_return", true);
exportHelper("nullability-arg", "nullability_arg", true);
exportHelper("nullability-return", "nullability_return", true);
exportHelper("cfi-check-fail", "cfi_check_fail", true);
exportHelper("function-type-mismatch-v1", "function_type_mismatch_v1", true);
+ exportMinimal("builtin-unreachable", "builtin_unreachable", false);
+ exportMinimal("add-overflow", "add_overflow", true);
+ exportMinimal("sub-overflow", "sub_overflow", true);
+ exportMinimal("mul-overflow", "mul_overflow", true);
+ exportMinimal("negation-handler", "negate_overflow", true);
+ exportMinimal("divrem-handler", "divrem_overflow", true);
+ exportMinimal("alignment-assumption-handler", "alignment_assumption", true);
+ exportMinimal("shift-oob", "shift_out_of_bounds", true);
+ exportMinimal("out-of-bounds", "out_of_bounds", true);
+ exportMinimal("pointer-overflow", "pointer_overflow", true);
+ exportMinimal("type-mismatch", "type_mismatch", true);
+
// these checks are nearly impossible to duplicate in zig, as they rely on nuances
// in the Itanium C++ ABI.
// exportHelper("dynamic_type_cache_miss", "dynamic-type-cache-miss", true);