mirror of
https://codeberg.org/ziglang/zig.git
synced 2025-12-06 13:54:21 +00:00
ubsan: avoid depending on @returnAddress combined with inline
This commit is contained in:
parent
44d3b5a6e4
commit
d4413e3504
1 changed files with 48 additions and 33 deletions
|
|
@ -1,6 +1,7 @@
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const builtin = @import("builtin");
|
const builtin = @import("builtin");
|
||||||
const assert = std.debug.assert;
|
const assert = std.debug.assert;
|
||||||
|
const panic = std.debug.panicExtra;
|
||||||
|
|
||||||
const SourceLocation = extern struct {
|
const SourceLocation = extern struct {
|
||||||
file_name: ?[*:0]const u8,
|
file_name: ?[*:0]const u8,
|
||||||
|
|
@ -175,7 +176,7 @@ fn overflowHandler(
|
||||||
const fmt = "{s} integer overflow: " ++ "{} " ++
|
const fmt = "{s} integer overflow: " ++ "{} " ++
|
||||||
operator ++ " {} cannot be represented in type {s}";
|
operator ++ " {} cannot be represented in type {s}";
|
||||||
|
|
||||||
logMessage(fmt, .{
|
panic(@returnAddress(), fmt, .{
|
||||||
if (is_signed) "signed" else "unsigned",
|
if (is_signed) "signed" else "unsigned",
|
||||||
lhs,
|
lhs,
|
||||||
rhs,
|
rhs,
|
||||||
|
|
@ -199,7 +200,8 @@ fn negationHandler(
|
||||||
value_handle: ValueHandle,
|
value_handle: ValueHandle,
|
||||||
) callconv(.c) noreturn {
|
) callconv(.c) noreturn {
|
||||||
const value: Value = .{ .handle = value_handle, .td = data.td };
|
const value: Value = .{ .handle = value_handle, .td = data.td };
|
||||||
logMessage(
|
panic(
|
||||||
|
@returnAddress(),
|
||||||
"negation of {} cannot be represented in type {s}",
|
"negation of {} cannot be represented in type {s}",
|
||||||
.{ value, data.td.getName() },
|
.{ value, data.td.getName() },
|
||||||
);
|
);
|
||||||
|
|
@ -222,11 +224,12 @@ fn divRemHandler(
|
||||||
const rhs: Value = .{ .handle = rhs_handle, .td = data.td };
|
const rhs: Value = .{ .handle = rhs_handle, .td = data.td };
|
||||||
|
|
||||||
if (rhs.isMinusOne()) {
|
if (rhs.isMinusOne()) {
|
||||||
logMessage(
|
panic(
|
||||||
|
@returnAddress(),
|
||||||
"division of {} by -1 cannot be represented in type {s}",
|
"division of {} by -1 cannot be represented in type {s}",
|
||||||
.{ lhs, data.td.getName() },
|
.{ lhs, data.td.getName() },
|
||||||
);
|
);
|
||||||
} else logMessage("division by zero", .{});
|
} else panic(@returnAddress(), "division by zero", .{});
|
||||||
}
|
}
|
||||||
|
|
||||||
const AlignmentAssumptionData = extern struct {
|
const AlignmentAssumptionData = extern struct {
|
||||||
|
|
@ -263,7 +266,8 @@ fn alignmentAssumptionHandler(
|
||||||
const alignment: Value = .{ .handle = alignment_handle, .td = data.td };
|
const alignment: Value = .{ .handle = alignment_handle, .td = data.td };
|
||||||
|
|
||||||
if (maybe_offset) |offset| {
|
if (maybe_offset) |offset| {
|
||||||
logMessage(
|
panic(
|
||||||
|
@returnAddress(),
|
||||||
"assumption of {} byte alignment (with offset of {} byte) for pointer of type {s} failed\n" ++
|
"assumption of {} byte alignment (with offset of {} byte) for pointer of type {s} failed\n" ++
|
||||||
"offset address is {} aligned, misalignment offset is {} bytes",
|
"offset address is {} aligned, misalignment offset is {} bytes",
|
||||||
.{
|
.{
|
||||||
|
|
@ -275,7 +279,8 @@ fn alignmentAssumptionHandler(
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
logMessage(
|
panic(
|
||||||
|
@returnAddress(),
|
||||||
"assumption of {} byte alignment for pointer of type {s} failed\n" ++
|
"assumption of {} byte alignment for pointer of type {s} failed\n" ++
|
||||||
"address is {} aligned, misalignment offset is {} bytes",
|
"address is {} aligned, misalignment offset is {} bytes",
|
||||||
.{
|
.{
|
||||||
|
|
@ -314,18 +319,20 @@ fn shiftOob(
|
||||||
rhs.getPositiveInteger() >= data.lhs_type.getIntegerSize())
|
rhs.getPositiveInteger() >= data.lhs_type.getIntegerSize())
|
||||||
{
|
{
|
||||||
if (rhs.isNegative()) {
|
if (rhs.isNegative()) {
|
||||||
logMessage("shift exponent {} is negative", .{rhs});
|
panic(@returnAddress(), "shift exponent {} is negative", .{rhs});
|
||||||
} else {
|
} else {
|
||||||
logMessage(
|
panic(
|
||||||
|
@returnAddress(),
|
||||||
"shift exponent {} is too large for {}-bit type {s}",
|
"shift exponent {} is too large for {}-bit type {s}",
|
||||||
.{ rhs, data.lhs_type.getIntegerSize(), data.lhs_type.getName() },
|
.{ rhs, data.lhs_type.getIntegerSize(), data.lhs_type.getName() },
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (lhs.isNegative()) {
|
if (lhs.isNegative()) {
|
||||||
logMessage("left shift of negative value {}", .{lhs});
|
panic(@returnAddress(), "left shift of negative value {}", .{lhs});
|
||||||
} else {
|
} else {
|
||||||
logMessage(
|
panic(
|
||||||
|
@returnAddress(),
|
||||||
"left shift of {} by {} places cannot be represented in type {s}",
|
"left shift of {} by {} places cannot be represented in type {s}",
|
||||||
.{ lhs, rhs, data.lhs_type.getName() },
|
.{ lhs, rhs, data.lhs_type.getName() },
|
||||||
);
|
);
|
||||||
|
|
@ -351,7 +358,8 @@ fn outOfBounds(
|
||||||
index_handle: ValueHandle,
|
index_handle: ValueHandle,
|
||||||
) callconv(.c) noreturn {
|
) callconv(.c) noreturn {
|
||||||
const index: Value = .{ .handle = index_handle, .td = data.index_type };
|
const index: Value = .{ .handle = index_handle, .td = data.index_type };
|
||||||
logMessage(
|
panic(
|
||||||
|
@returnAddress(),
|
||||||
"index {} out of bounds for type {s}",
|
"index {} out of bounds for type {s}",
|
||||||
.{ index, data.array_type.getName() },
|
.{ index, data.array_type.getName() },
|
||||||
);
|
);
|
||||||
|
|
@ -376,13 +384,14 @@ fn pointerOverflow(
|
||||||
) callconv(.c) noreturn {
|
) callconv(.c) noreturn {
|
||||||
if (base == 0) {
|
if (base == 0) {
|
||||||
if (result == 0) {
|
if (result == 0) {
|
||||||
logMessage("applying zero offset to null pointer", .{});
|
panic(@returnAddress(), "applying zero offset to null pointer", .{});
|
||||||
} else {
|
} else {
|
||||||
logMessage("applying non-zero offset {} to null pointer", .{result});
|
panic(@returnAddress(), "applying non-zero offset {} to null pointer", .{result});
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (result == 0) {
|
if (result == 0) {
|
||||||
logMessage(
|
panic(
|
||||||
|
@returnAddress(),
|
||||||
"applying non-zero offset to non-null pointer 0x{x} produced null pointer",
|
"applying non-zero offset to non-null pointer 0x{x} produced null pointer",
|
||||||
.{base},
|
.{base},
|
||||||
);
|
);
|
||||||
|
|
@ -391,18 +400,21 @@ fn pointerOverflow(
|
||||||
const signed_result: isize = @bitCast(result);
|
const signed_result: isize = @bitCast(result);
|
||||||
if ((signed_base >= 0) == (signed_result >= 0)) {
|
if ((signed_base >= 0) == (signed_result >= 0)) {
|
||||||
if (base > result) {
|
if (base > result) {
|
||||||
logMessage(
|
panic(
|
||||||
|
@returnAddress(),
|
||||||
"addition of unsigned offset to 0x{x} overflowed to 0x{x}",
|
"addition of unsigned offset to 0x{x} overflowed to 0x{x}",
|
||||||
.{ base, result },
|
.{ base, result },
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
logMessage(
|
panic(
|
||||||
|
@returnAddress(),
|
||||||
"subtraction of unsigned offset to 0x{x} overflowed to 0x{x}",
|
"subtraction of unsigned offset to 0x{x} overflowed to 0x{x}",
|
||||||
.{ base, result },
|
.{ base, result },
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
logMessage(
|
panic(
|
||||||
|
@returnAddress(),
|
||||||
"pointer index expression with base 0x{x} overflowed to 0x{x}",
|
"pointer index expression with base 0x{x} overflowed to 0x{x}",
|
||||||
.{ base, result },
|
.{ base, result },
|
||||||
);
|
);
|
||||||
|
|
@ -462,17 +474,20 @@ fn typeMismatch(
|
||||||
const handle: usize = @intFromPtr(pointer);
|
const handle: usize = @intFromPtr(pointer);
|
||||||
|
|
||||||
if (pointer == null) {
|
if (pointer == null) {
|
||||||
logMessage(
|
panic(
|
||||||
|
@returnAddress(),
|
||||||
"{s} null pointer of type {s}",
|
"{s} null pointer of type {s}",
|
||||||
.{ data.kind.getName(), data.td.getName() },
|
.{ data.kind.getName(), data.td.getName() },
|
||||||
);
|
);
|
||||||
} else if (!std.mem.isAligned(handle, alignment)) {
|
} else if (!std.mem.isAligned(handle, alignment)) {
|
||||||
logMessage(
|
panic(
|
||||||
|
@returnAddress(),
|
||||||
"{s} misaligned address 0x{x} for type {s}, which requires {} byte alignment",
|
"{s} misaligned address 0x{x} for type {s}, which requires {} byte alignment",
|
||||||
.{ data.kind.getName(), handle, data.td.getName(), alignment },
|
.{ data.kind.getName(), handle, data.td.getName(), alignment },
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
logMessage(
|
panic(
|
||||||
|
@returnAddress(),
|
||||||
"{s} address 0x{x} with insufficient space for an object of type {s}",
|
"{s} address 0x{x} with insufficient space for an object of type {s}",
|
||||||
.{ data.kind.getName(), handle, data.td.getName() },
|
.{ data.kind.getName(), handle, data.td.getName() },
|
||||||
);
|
);
|
||||||
|
|
@ -484,11 +499,11 @@ const UnreachableData = extern struct {
|
||||||
};
|
};
|
||||||
|
|
||||||
fn builtinUnreachable(_: *const UnreachableData) callconv(.c) noreturn {
|
fn builtinUnreachable(_: *const UnreachableData) callconv(.c) noreturn {
|
||||||
logMessage("execution reached an unreachable program point", .{});
|
panic(@returnAddress(), "execution reached an unreachable program point", .{});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn missingReturn(_: *const UnreachableData) callconv(.c) noreturn {
|
fn missingReturn(_: *const UnreachableData) callconv(.c) noreturn {
|
||||||
logMessage("execution reached the end of a value-returning function without returning a value", .{});
|
panic(@returnAddress(), "execution reached the end of a value-returning function without returning a value", .{});
|
||||||
}
|
}
|
||||||
|
|
||||||
const NonNullReturnData = extern struct {
|
const NonNullReturnData = extern struct {
|
||||||
|
|
@ -499,7 +514,7 @@ fn nonNullReturnAbort(data: *const NonNullReturnData) callconv(.c) noreturn {
|
||||||
nonNullReturn(data);
|
nonNullReturn(data);
|
||||||
}
|
}
|
||||||
fn nonNullReturn(_: *const NonNullReturnData) callconv(.c) noreturn {
|
fn nonNullReturn(_: *const NonNullReturnData) callconv(.c) noreturn {
|
||||||
logMessage("null pointer returned from function declared to never return null", .{});
|
panic(@returnAddress(), "null pointer returned from function declared to never return null", .{});
|
||||||
}
|
}
|
||||||
|
|
||||||
const NonNullArgData = extern struct {
|
const NonNullArgData = extern struct {
|
||||||
|
|
@ -513,7 +528,8 @@ fn nonNullArgAbort(data: *const NonNullArgData) callconv(.c) noreturn {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn nonNullArg(data: *const NonNullArgData) callconv(.c) noreturn {
|
fn nonNullArg(data: *const NonNullArgData) callconv(.c) noreturn {
|
||||||
logMessage(
|
panic(
|
||||||
|
@returnAddress(),
|
||||||
"null pointer passed as argument {}, which is declared to never be null",
|
"null pointer passed as argument {}, which is declared to never be null",
|
||||||
.{data.arg_index},
|
.{data.arg_index},
|
||||||
);
|
);
|
||||||
|
|
@ -536,7 +552,8 @@ fn loadInvalidValue(
|
||||||
value_handle: ValueHandle,
|
value_handle: ValueHandle,
|
||||||
) callconv(.c) noreturn {
|
) callconv(.c) noreturn {
|
||||||
const value: Value = .{ .handle = value_handle, .td = data.td };
|
const value: Value = .{ .handle = value_handle, .td = data.td };
|
||||||
logMessage(
|
panic(
|
||||||
|
@returnAddress(),
|
||||||
"load of value {}, which is not valid for type {s}",
|
"load of value {}, which is not valid for type {s}",
|
||||||
.{ value, data.td.getName() },
|
.{ value, data.td.getName() },
|
||||||
);
|
);
|
||||||
|
|
@ -554,7 +571,8 @@ fn invalidBuiltinAbort(data: *const InvalidBuiltinData) callconv(.c) noreturn {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn invalidBuiltin(data: *const InvalidBuiltinData) callconv(.c) noreturn {
|
fn invalidBuiltin(data: *const InvalidBuiltinData) callconv(.c) noreturn {
|
||||||
logMessage(
|
panic(
|
||||||
|
@returnAddress(),
|
||||||
"passing zero to {s}(), which is not a valid argument",
|
"passing zero to {s}(), which is not a valid argument",
|
||||||
.{@tagName(data.kind)},
|
.{@tagName(data.kind)},
|
||||||
);
|
);
|
||||||
|
|
@ -577,7 +595,8 @@ fn vlaBoundNotPositive(
|
||||||
bound_handle: ValueHandle,
|
bound_handle: ValueHandle,
|
||||||
) callconv(.c) noreturn {
|
) callconv(.c) noreturn {
|
||||||
const bound: Value = .{ .handle = bound_handle, .td = data.td };
|
const bound: Value = .{ .handle = bound_handle, .td = data.td };
|
||||||
logMessage(
|
panic(
|
||||||
|
@returnAddress(),
|
||||||
"variable length array bound evaluates to non-positive value {}",
|
"variable length array bound evaluates to non-positive value {}",
|
||||||
.{bound},
|
.{bound},
|
||||||
);
|
);
|
||||||
|
|
@ -611,22 +630,18 @@ fn floatCastOverflow(
|
||||||
if (@as(u16, ptr[0]) + @as(u16, ptr[1]) < 2 or ptr[0] == 0xFF or ptr[1] == 0xFF) {
|
if (@as(u16, ptr[0]) + @as(u16, ptr[1]) < 2 or ptr[0] == 0xFF or ptr[1] == 0xFF) {
|
||||||
const data: *const FloatCastOverflowData = @ptrCast(data_handle);
|
const data: *const FloatCastOverflowData = @ptrCast(data_handle);
|
||||||
const from_value: Value = .{ .handle = from_handle, .td = data.from };
|
const from_value: Value = .{ .handle = from_handle, .td = data.from };
|
||||||
logMessage("{} is outside the range of representable values of type {s}", .{
|
panic(@returnAddress(), "{} is outside the range of representable values of type {s}", .{
|
||||||
from_value, data.to.getName(),
|
from_value, data.to.getName(),
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
const data: *const FloatCastOverflowDataV2 = @ptrCast(data_handle);
|
const data: *const FloatCastOverflowDataV2 = @ptrCast(data_handle);
|
||||||
const from_value: Value = .{ .handle = from_handle, .td = data.from };
|
const from_value: Value = .{ .handle = from_handle, .td = data.from };
|
||||||
logMessage("{} is outside the range of representable values of type {s}", .{
|
panic(@returnAddress(), "{} is outside the range of representable values of type {s}", .{
|
||||||
from_value, data.to.getName(),
|
from_value, data.to.getName(),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline fn logMessage(comptime fmt: []const u8, args: anytype) noreturn {
|
|
||||||
std.debug.panicExtra(@returnAddress(), fmt, args);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn exportHandler(
|
fn exportHandler(
|
||||||
handler: anytype,
|
handler: anytype,
|
||||||
comptime sym_name: []const u8,
|
comptime sym_name: []const u8,
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue