authorgravatar for robin@voetter.nlRobin Voetter <robin@voetter.nl> 2021-08-19 07:20:50+02:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2021-08-19 01:20:50-04:00
log5cd1d42a351aa77d2a030e59cbd2b9abf7c44444
tree0b77571b84b460729315a223f60134f2c6436a88
parent4c9d41730e66b253d12472d616e3a519c79a41cb
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Add mask before truncating dereferenced bit pointers (#9584)


3 files changed, 69 insertions(+), 5 deletions(-)

src/stage1/codegen.cpp+8-5
...@@ -3831,10 +3831,14 @@ static LLVMValueRef ir_render_load_ptr(CodeGen *g, Stage1Air *executable,...@@ -3831,10 +3831,14 @@ static LLVMValueRef ir_render_load_ptr(CodeGen *g, Stage1Air *executable,
3831 LLVMValueRef shift_amt_val = LLVMConstInt(LLVMTypeOf(containing_int), shift_amt, false);3831 LLVMValueRef shift_amt_val = LLVMConstInt(LLVMTypeOf(containing_int), shift_amt, false);
3832 LLVMValueRef shifted_value = LLVMBuildLShr(g->builder, containing_int, shift_amt_val, "");3832 LLVMValueRef shifted_value = LLVMBuildLShr(g->builder, containing_int, shift_amt_val, "");
38333833
3834 LLVMTypeRef same_size_int = LLVMIntType(size_in_bits);
3835 LLVMValueRef mask = LLVMConstAllOnes(LLVMIntType(size_in_bits));
3836 mask = LLVMConstZExt(mask, LLVMTypeOf(containing_int));
3837 LLVMValueRef masked_value = LLVMBuildAnd(g->builder, shifted_value, mask, "");
3838
3834 if (handle_is_ptr(g, child_type)) {3839 if (handle_is_ptr(g, child_type)) {
3835 LLVMValueRef result_loc = ir_llvm_value(g, instruction->result_loc);3840 LLVMValueRef result_loc = ir_llvm_value(g, instruction->result_loc);
3836 LLVMTypeRef same_size_int = LLVMIntType(size_in_bits);3841 LLVMValueRef truncated_int = LLVMBuildTrunc(g->builder, masked_value, same_size_int, "");
3837 LLVMValueRef truncated_int = LLVMBuildTrunc(g->builder, shifted_value, same_size_int, "");
3838 LLVMValueRef bitcasted_ptr = LLVMBuildBitCast(g->builder, result_loc,3842 LLVMValueRef bitcasted_ptr = LLVMBuildBitCast(g->builder, result_loc,
3839 LLVMPointerType(same_size_int, 0), "");3843 LLVMPointerType(same_size_int, 0), "");
3840 LLVMBuildStore(g->builder, truncated_int, bitcasted_ptr);3844 LLVMBuildStore(g->builder, truncated_int, bitcasted_ptr);
...@@ -3842,12 +3846,11 @@ static LLVMValueRef ir_render_load_ptr(CodeGen *g, Stage1Air *executable,...@@ -3842,12 +3846,11 @@ static LLVMValueRef ir_render_load_ptr(CodeGen *g, Stage1Air *executable,
3842 }3846 }
38433847
3844 if (child_type->id == ZigTypeIdFloat) {3848 if (child_type->id == ZigTypeIdFloat) {
3845 LLVMTypeRef same_size_int = LLVMIntType(size_in_bits);3849 LLVMValueRef truncated_int = LLVMBuildTrunc(g->builder, masked_value, same_size_int, "");
3846 LLVMValueRef truncated_int = LLVMBuildTrunc(g->builder, shifted_value, same_size_int, "");
3847 return LLVMBuildBitCast(g->builder, truncated_int, get_llvm_type(g, child_type), "");3850 return LLVMBuildBitCast(g->builder, truncated_int, get_llvm_type(g, child_type), "");
3848 }3851 }
38493852
3850 return LLVMBuildTrunc(g->builder, shifted_value, get_llvm_type(g, child_type), "");3853 return LLVMBuildTrunc(g->builder, masked_value, get_llvm_type(g, child_type), "");
3851}3854}
38523855
3853static bool value_is_all_undef_array(CodeGen *g, ZigValue *const_val, size_t len) {3856static bool value_is_all_undef_array(CodeGen *g, ZigValue *const_val, size_t len) {
test/behavior.zig+1
...@@ -71,6 +71,7 @@ test {...@@ -71,6 +71,7 @@ test {
71 _ = @import("behavior/bugs/7047.zig");71 _ = @import("behavior/bugs/7047.zig");
72 _ = @import("behavior/bugs/7003.zig");72 _ = @import("behavior/bugs/7003.zig");
73 _ = @import("behavior/bugs/7250.zig");73 _ = @import("behavior/bugs/7250.zig");
74 _ = @import("behavior/bugs/9584.zig");
74 _ = @import("behavior/bugs/394.zig");75 _ = @import("behavior/bugs/394.zig");
75 _ = @import("behavior/bugs/421.zig");76 _ = @import("behavior/bugs/421.zig");
76 _ = @import("behavior/bugs/529.zig");77 _ = @import("behavior/bugs/529.zig");
test/behavior/bugs/9584.zig created+60
...@@ -0,0 +1,60 @@
1const std = @import("std");
2
3const A = packed struct {
4 a: bool,
5 b: bool,
6 c: bool,
7 d: bool,
8
9 e: bool,
10 f: bool,
11 g: bool,
12 h: bool,
13};
14
15const X = union {
16 x: A,
17 y: u64,
18};
19
20pub fn a(
21 x0: i32,
22 x1: i32,
23 x2: i32,
24 x3: i32,
25 x4: i32,
26 flag_a: bool,
27 flag_b: bool,
28) !void {
29 _ = x0;
30 _ = x1;
31 _ = x2;
32 _ = x3;
33 _ = x4;
34 _ = flag_a;
35 // With this bug present, `flag_b` would actually contain the value 17.
36 // Note: this bug only presents itself on debug mode.
37 try std.testing.expect(@ptrCast(*const u8, &flag_b).* == 1);
38}
39
40pub fn b(x: *X) !void {
41 try a(0, 1, 2, 3, 4, x.x.a, x.x.b);
42}
43
44test "bug 9584" {
45 var flags = A{
46 .a = false,
47 .b = true,
48 .c = false,
49 .d = false,
50
51 .e = false,
52 .f = true,
53 .g = false,
54 .h = false,
55 };
56 var x = X{
57 .x = flags,
58 };
59 try b(&x);
60}