authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2022-07-16 23:46:24+03:00
committergravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2022-07-23 15:40:11+03:00
logcf87026e52f7faa090c5fa922d5649f5ec2f1831
tree0320fb49ca87a1dad636d19555145cdb77c5a8ff
parent711b656773fe1d3840c74a4ea1e526ae9bf589fb

Sema: `@alignCast` safety


4 files changed, 47 insertions(+), 17 deletions(-)

src/Sema.zig+30-2
...@@ -16278,8 +16278,6 @@ fn zirAlignCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A...@@ -16278,8 +16278,6 @@ fn zirAlignCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
16278 // TODO compile error if the result pointer is comptime known and would have an16278 // TODO compile error if the result pointer is comptime known and would have an
16279 // alignment that disagrees with the Decl's alignment.16279 // alignment that disagrees with the Decl's alignment.
1628016280
16281 // TODO insert safety check that the alignment is correct
16282
16283 const ptr_info = ptr_ty.ptrInfo().data;16281 const ptr_info = ptr_ty.ptrInfo().data;
16284 const dest_ty = try Type.ptr(sema.arena, sema.mod, .{16282 const dest_ty = try Type.ptr(sema.arena, sema.mod, .{
16285 .pointee_type = ptr_info.pointee_type,16283 .pointee_type = ptr_info.pointee_type,
...@@ -16290,6 +16288,36 @@ fn zirAlignCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A...@@ -16290,6 +16288,36 @@ fn zirAlignCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
16290 .@"volatile" = ptr_info.@"volatile",16288 .@"volatile" = ptr_info.@"volatile",
16291 .size = ptr_info.size,16289 .size = ptr_info.size,
16292 });16290 });
16291
16292 if (try sema.resolveDefinedValue(block, ptr_src, ptr)) |val| {
16293 if (try val.getUnsignedIntAdvanced(sema.mod.getTarget(), null)) |addr| {
16294 if (addr % dest_align != 0) {
16295 return sema.fail(block, ptr_src, "pointer address 0x{X} is not aligned to {d} bytes", .{ addr, dest_align });
16296 }
16297 }
16298 return sema.addConstant(dest_ty, val);
16299 }
16300
16301 try sema.requireRuntimeBlock(block, inst_data.src(), ptr_src);
16302 if (block.wantSafety() and dest_align > 1) {
16303 const val_payload = try sema.arena.create(Value.Payload.U64);
16304 val_payload.* = .{
16305 .base = .{ .tag = .int_u64 },
16306 .data = dest_align - 1,
16307 };
16308 const align_minus_1 = try sema.addConstant(
16309 Type.usize,
16310 Value.initPayload(&val_payload.base),
16311 );
16312 const actual_ptr = if (ptr_ty.isSlice())
16313 try sema.analyzeSlicePtr(block, ptr_src, ptr, ptr_ty)
16314 else
16315 ptr;
16316 const ptr_int = try block.addUnOp(.ptrtoint, actual_ptr);
16317 const remainder = try block.addBinOp(.bit_and, ptr_int, align_minus_1);
16318 const is_aligned = try block.addBinOp(.cmp_eq, remainder, .zero_usize);
16319 try sema.addSafetyCheck(block, is_aligned, .incorrect_alignment);
16320 }
16293 return sema.coerceCompatiblePtrs(block, dest_ty, ptr, ptr_src);16321 return sema.coerceCompatiblePtrs(block, dest_ty, ptr, ptr_src);
16294}16322}
1629516323
test/cases/compile_errors/bad_alignCast_at_comptime.zig created+11
...@@ -0,0 +1,11 @@
1comptime {
2 const ptr = @intToPtr(*align(1) i32, 0x1);
3 const aligned = @alignCast(4, ptr);
4 _ = aligned;
5}
6
7// error
8// backend=stage2
9// target=native
10//
11// :3:35: error: pointer address 0x1 is not aligned to 4 bytes
test/cases/compile_errors/stage1/obj/bad_alignCast_at_comptime.zig deleted-11
...@@ -1,11 +0,0 @@
1comptime {
2 const ptr = @intToPtr(*align(1) i32, 0x1);
3 const aligned = @alignCast(4, ptr);
4 _ = aligned;
5}
6
7// error
8// backend=stage1
9// target=native
10//
11// tmp.zig:3:35: error: pointer address 0x1 is not aligned to 4 bytes
test/cases/safety/@alignCast misaligned.zig +6-4
...@@ -1,9 +1,11 @@...@@ -1,9 +1,11 @@
1const std = @import("std");1const std = @import("std");
22
3pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {3pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
4 _ = message;
5 _ = stack_trace;4 _ = stack_trace;
6 std.process.exit(0);5 if (std.mem.eql(u8, message, "incorrect alignment")) {
6 std.process.exit(0);
7 }
8 std.process.exit(1);
7}9}
810
9pub fn main() !void {11pub fn main() !void {
...@@ -18,5 +20,5 @@ fn foo(bytes: []u8) u32 {...@@ -18,5 +20,5 @@ fn foo(bytes: []u8) u32 {
18 return int_slice[0];20 return int_slice[0];
19}21}
20// run22// run
21// backend=stage1
22// target=native
\ No newline at end of file
23// backend=llvm
24// target=native