authorgravatar for david@vortan.devDavid Rubin <david@vortan.dev> 2024-12-26 17:46:28-08:00
committergravatar for david@vortan.devDavid Rubin <david@vortan.dev> 2025-02-25 11:22:33-08:00
logd669b9520b85aa5e892fe073b2c485f1bf1afef5
treed5c776bf671626f710a738058b422837c9f74507
parent14178475e35674122c65d11c8f0957c89e10506c

ubsan: clean-up a bit more


1 files changed, 53 insertions(+), 52 deletions(-)

lib/ubsan.zig+53-52
......@@ -42,19 +42,15 @@ const TypeDescriptor = extern struct {
4242 }
4343};
4444
45const ValueHandle = *const opaque {
46 fn getValue(handle: ValueHandle, data: anytype) Value {
47 return .{ .handle = handle, .type_descriptor = data.type_descriptor };
48 }
49};
45const ValueHandle = *const opaque {};
5046
5147const Value = extern struct {
52 type_descriptor: *const TypeDescriptor,
48 td: *const TypeDescriptor,
5349 handle: ValueHandle,
5450
5551 fn getUnsignedInteger(value: Value) u128 {
56 assert(!value.type_descriptor.isSigned());
57 const size = value.type_descriptor.getIntegerSize();
52 assert(!value.td.isSigned());
53 const size = value.td.getIntegerSize();
5854 const max_inline_size = @bitSizeOf(ValueHandle);
5955 if (size <= max_inline_size) {
6056 return @intFromPtr(value.handle);
......@@ -68,8 +64,8 @@ const Value = extern struct {
6864 }
6965
7066 fn getSignedInteger(value: Value) i128 {
71 assert(value.type_descriptor.isSigned());
72 const size = value.type_descriptor.getIntegerSize();
67 assert(value.td.isSigned());
68 const size = value.td.getIntegerSize();
7369 const max_inline_size = @bitSizeOf(ValueHandle);
7470 if (size <= max_inline_size) {
7571 const extra_bits: std.math.Log2Int(usize) = @intCast(max_inline_size - size);
......@@ -84,8 +80,8 @@ const Value = extern struct {
8480 }
8581
8682 fn getFloat(value: Value) c_longdouble {
87 assert(value.type_descriptor.kind == .float);
88 const size = value.type_descriptor.info.float;
83 assert(value.td.kind == .float);
84 const size = value.td.info.float;
8985 const max_inline_size = @bitSizeOf(ValueHandle);
9086 if (size <= max_inline_size) {
9187 return @bitCast(@intFromPtr(value.handle));
......@@ -99,17 +95,17 @@ const Value = extern struct {
9995 }
10096
10197 fn isMinusOne(value: Value) bool {
102 return value.type_descriptor.isSigned() and
98 return value.td.isSigned() and
10399 value.getSignedInteger() == -1;
104100 }
105101
106102 fn isNegative(value: Value) bool {
107 return value.type_descriptor.isSigned() and
103 return value.td.isSigned() and
108104 value.getSignedInteger() < 0;
109105 }
110106
111107 fn getPositiveInteger(value: Value) u128 {
112 if (value.type_descriptor.isSigned()) {
108 if (value.td.isSigned()) {
113109 const signed = value.getSignedInteger();
114110 assert(signed >= 0);
115111 return @intCast(signed);
......@@ -126,9 +122,9 @@ const Value = extern struct {
126122 ) !void {
127123 comptime assert(fmt.len == 0);
128124
129 switch (value.type_descriptor.kind) {
125 switch (value.td.kind) {
130126 .integer => {
131 if (value.type_descriptor.isSigned()) {
127 if (value.td.isSigned()) {
132128 try writer.print("{}", .{value.getSignedInteger()});
133129 } else {
134130 try writer.print("{}", .{value.getUnsignedInteger()});
......@@ -142,7 +138,7 @@ const Value = extern struct {
142138
143139const OverflowData = extern struct {
144140 loc: SourceLocation,
145 type_descriptor: *const TypeDescriptor,
141 td: *const TypeDescriptor,
146142};
147143
148144fn overflowHandler(
......@@ -155,10 +151,10 @@ fn overflowHandler(
155151 lhs_handle: ValueHandle,
156152 rhs_handle: ValueHandle,
157153 ) callconv(.c) noreturn {
158 const lhs = lhs_handle.getValue(data);
159 const rhs = rhs_handle.getValue(data);
154 const lhs: Value = .{ .handle = lhs_handle, .td = data.td };
155 const rhs: Value = .{ .handle = rhs_handle, .td = data.td };
160156
161 const is_signed = data.type_descriptor.isSigned();
157 const is_signed = data.td.isSigned();
162158 const fmt = "{s} integer overflow: " ++ "{} " ++
163159 operator ++ " {} cannot be represented in type {s}";
164160
......@@ -166,7 +162,7 @@ fn overflowHandler(
166162 if (is_signed) "signed" else "unsigned",
167163 lhs,
168164 rhs,
169 data.type_descriptor.getName(),
165 data.td.getName(),
170166 });
171167 }
172168 };
......@@ -176,12 +172,12 @@ fn overflowHandler(
176172
177173fn negationHandler(
178174 data: *const OverflowData,
179 old_value_handle: ValueHandle,
175 value_handle: ValueHandle,
180176) callconv(.c) noreturn {
181 const old_value = old_value_handle.getValue(data);
177 const value: Value = .{ .handle = value_handle, .td = data.td };
182178 logMessage(
183179 "negation of {} cannot be represented in type {s}",
184 .{ old_value, data.type_descriptor.getName() },
180 .{ value, data.td.getName() },
185181 );
186182}
187183
......@@ -190,13 +186,13 @@ fn divRemHandler(
190186 lhs_handle: ValueHandle,
191187 rhs_handle: ValueHandle,
192188) callconv(.c) noreturn {
193 const lhs = lhs_handle.getValue(data);
194 const rhs = rhs_handle.getValue(data);
189 const lhs: Value = .{ .handle = lhs_handle, .td = data.lhs_type };
190 const rhs: Value = .{ .handle = rhs_handle, .td = data.rhs_type };
195191
196192 if (rhs.isMinusOne()) {
197193 logMessage(
198194 "division of {} by -1 cannot be represented in type {s}",
199 .{ lhs, data.type_descriptor.getName() },
195 .{ lhs, data.td.getName() },
200196 );
201197 } else logMessage("division by zero", .{});
202198}
......@@ -204,29 +200,30 @@ fn divRemHandler(
204200const AlignmentAssumptionData = extern struct {
205201 loc: SourceLocation,
206202 assumption_loc: SourceLocation,
207 type_descriptor: *const TypeDescriptor,
203 td: *const TypeDescriptor,
208204};
209205
210206fn alignmentAssumptionHandler(
211207 data: *const AlignmentAssumptionData,
212208 pointer: ValueHandle,
213 alignment: ValueHandle,
209 alignment_handle: ValueHandle,
214210 maybe_offset: ?ValueHandle,
215211) callconv(.c) noreturn {
216212 const real_pointer = @intFromPtr(pointer) - @intFromPtr(maybe_offset);
217213 const lsb = @ctz(real_pointer);
218214 const actual_alignment = @as(u64, 1) << @intCast(lsb);
219 const mask = @intFromPtr(alignment) - 1;
215 const mask = @intFromPtr(alignment_handle) - 1;
220216 const misalignment_offset = real_pointer & mask;
217 const alignment: Value = .{ .handle = alignment_handle, .td = data.td };
221218
222219 if (maybe_offset) |offset| {
223220 logMessage(
224221 "assumption of {} byte alignment (with offset of {} byte) for pointer of type {s} failed\n" ++
225222 "offset address is {} aligned, misalignment offset is {} bytes",
226223 .{
227 alignment.getValue(data),
224 alignment,
228225 @intFromPtr(offset),
229 data.type_descriptor.getName(),
226 data.td.getName(),
230227 actual_alignment,
231228 misalignment_offset,
232229 },
......@@ -236,8 +233,8 @@ fn alignmentAssumptionHandler(
236233 "assumption of {} byte alignment for pointer of type {s} failed\n" ++
237234 "address is {} aligned, misalignment offset is {} bytes",
238235 .{
239 alignment.getValue(data),
240 data.type_descriptor.getName(),
236 alignment,
237 data.td.getName(),
241238 actual_alignment,
242239 misalignment_offset,
243240 },
......@@ -256,8 +253,8 @@ fn shiftOob(
256253 lhs_handle: ValueHandle,
257254 rhs_handle: ValueHandle,
258255) callconv(.c) noreturn {
259 const lhs: Value = .{ .handle = lhs_handle, .type_descriptor = data.lhs_type };
260 const rhs: Value = .{ .handle = rhs_handle, .type_descriptor = data.rhs_type };
256 const lhs: Value = .{ .handle = lhs_handle, .td = data.lhs_type };
257 const rhs: Value = .{ .handle = rhs_handle, .td = data.rhs_type };
261258
262259 if (rhs.isNegative() or
263260 rhs.getPositiveInteger() >= data.lhs_type.getIntegerSize())
......@@ -289,7 +286,7 @@ const OutOfBoundsData = extern struct {
289286};
290287
291288fn outOfBounds(data: *const OutOfBoundsData, index_handle: ValueHandle) callconv(.c) noreturn {
292 const index: Value = .{ .handle = index_handle, .type_descriptor = data.index_type };
289 const index: Value = .{ .handle = index_handle, .td = data.index_type };
293290 logMessage(
294291 "index {} out of bounds for type {s}",
295292 .{ index, data.array_type.getName() },
......@@ -344,7 +341,7 @@ fn pointerOverflow(
344341
345342const TypeMismatchData = extern struct {
346343 loc: SourceLocation,
347 type_descriptor: *const TypeDescriptor,
344 td: *const TypeDescriptor,
348345 log_alignment: u8,
349346 kind: enum(u8) {
350347 load,
......@@ -388,17 +385,17 @@ fn typeMismatch(
388385 if (pointer == null) {
389386 logMessage(
390387 "{s} null pointer of type {s}",
391 .{ data.kind.getName(), data.type_descriptor.getName() },
388 .{ data.kind.getName(), data.td.getName() },
392389 );
393390 } else if (!std.mem.isAligned(handle, alignment)) {
394391 logMessage(
395392 "{s} misaligned address 0x{x} for type {s}, which requires {} byte alignment",
396 .{ data.kind.getName(), handle, data.type_descriptor.getName(), alignment },
393 .{ data.kind.getName(), handle, data.td.getName(), alignment },
397394 );
398395 } else {
399396 logMessage(
400397 "{s} address 0x{x} with insufficient space for an object of type {s}",
401 .{ data.kind.getName(), handle, data.type_descriptor.getName() },
398 .{ data.kind.getName(), handle, data.td.getName() },
402399 );
403400 }
404401}
......@@ -438,16 +435,18 @@ fn nonNullArg(data: *const NonNullArgData) callconv(.c) noreturn {
438435
439436const InvalidValueData = extern struct {
440437 loc: SourceLocation,
441 type_descriptor: *const TypeDescriptor,
438 td: *const TypeDescriptor,
442439};
443440
444441fn loadInvalidValue(
445442 data: *const InvalidValueData,
446443 value_handle: ValueHandle,
447444) callconv(.c) noreturn {
448 logMessage("load of value {}, which is not valid for type {s}", .{
449 value_handle.getValue(data), data.type_descriptor.getName(),
450 });
445 const value: Value = .{ .handle = value_handle, .td = data.td };
446 logMessage(
447 "load of value {}, which is not valid for type {s}",
448 .{ value, data.td.getName() },
449 );
451450}
452451
453452const InvalidBuiltinData = extern struct {
......@@ -467,16 +466,18 @@ fn invalidBuiltin(data: *const InvalidBuiltinData) callconv(.c) noreturn {
467466
468467const VlaBoundNotPositive = extern struct {
469468 loc: SourceLocation,
470 type_descriptor: *const TypeDescriptor,
469 td: *const TypeDescriptor,
471470};
472471
473472fn vlaBoundNotPositive(
474473 data: *const VlaBoundNotPositive,
475474 bound_handle: ValueHandle,
476475) callconv(.c) noreturn {
477 logMessage("variable length array bound evaluates to non-positive value {}", .{
478 bound_handle.getValue(data),
479 });
476 const bound: Value = .{ .handle = bound_handle, .td = data.td };
477 logMessage(
478 "variable length array bound evaluates to non-positive value {}",
479 .{bound},
480 );
480481}
481482
482483const FloatCastOverflowData = extern struct {
......@@ -499,13 +500,13 @@ fn floatCastOverflow(
499500 const ptr: [*]const u8 = @ptrCast(data_handle);
500501 if (@as(u16, ptr[0]) + @as(u16, ptr[1]) < 2 or ptr[0] == 0xFF or ptr[1] == 0xFF) {
501502 const data: *const FloatCastOverflowData = @ptrCast(data_handle);
502 const from_value: Value = .{ .handle = from_handle, .type_descriptor = data.from };
503 const from_value: Value = .{ .handle = from_handle, .td = data.from };
503504 logMessage("{} is outside the range of representable values of type {s}", .{
504505 from_value, data.to.getName(),
505506 });
506507 } else {
507508 const data: *const FloatCastOverflowDataV2 = @ptrCast(data_handle);
508 const from_value: Value = .{ .handle = from_handle, .type_descriptor = data.from };
509 const from_value: Value = .{ .handle = from_handle, .td = data.from };
509510 logMessage("{} is outside the range of representable values of type {s}", .{
510511 from_value, data.to.getName(),
511512 });