From ff7ec4efb5a6da565b92bc7b129d03680a4a72bd Mon Sep 17 00:00:00 2001 From: Veikka Tuominen Date: Sat, 16 Jul 2022 16:32:49 +0300 Subject: Sema: bad union field access safety --- test/behavior/bugs/1381.zig | 2 ++ test/behavior/struct.zig | 3 +++ test/behavior/type.zig | 2 +- test/behavior/union.zig | 13 +++++++++++++ .../wrong_initializer_for_union_payload_of_type_type.zig | 3 +-- test/cases/safety/bad union field access.zig | 10 ++++++---- 6 files changed, 26 insertions(+), 7 deletions(-) (limited to 'test') diff --git a/test/behavior/bugs/1381.zig b/test/behavior/bugs/1381.zig index ae80132cc1..002d217434 100644 --- a/test/behavior/bugs/1381.zig +++ b/test/behavior/bugs/1381.zig @@ -12,8 +12,10 @@ const A = union(enum) { }; test "union that needs padding bytes inside an array" { + if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; + if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; var as = [_]A{ A{ .B = B{ .D = 1 } }, diff --git a/test/behavior/struct.zig b/test/behavior/struct.zig index 22d09a066d..8fac5697ec 100644 --- a/test/behavior/struct.zig +++ b/test/behavior/struct.zig @@ -998,6 +998,9 @@ test "tuple element initialized with fn call" { } test "struct with union field" { + if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO + const Value = struct { ref: u32 = 2, kind: union(enum) { diff --git a/test/behavior/type.zig b/test/behavior/type.zig index f4a32e5df0..16a79a5122 100644 --- a/test/behavior/type.zig +++ b/test/behavior/type.zig @@ -412,7 +412,7 @@ test "Type.Union" { const Untagged = @Type(.{ .Union = .{ - .layout = .Auto, + .layout = .Extern, .tag_type = null, .fields = &.{ .{ .name = "int", .field_type = i32, .alignment = @alignOf(f32) }, diff --git a/test/behavior/union.zig b/test/behavior/union.zig index 1787a9f30e..8e4b262565 100644 --- a/test/behavior/union.zig +++ b/test/behavior/union.zig @@ -37,6 +37,7 @@ test "init union with runtime value - floats" { test "basic unions" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; + if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO var foo = Foo{ .int = 1 }; try expect(foo.int == 1); @@ -430,9 +431,11 @@ const Foo1 = union(enum) { var glbl: Foo1 = undefined; test "global union with single field is correctly initialized" { + if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; + if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO glbl = Foo1{ .f = @typeInfo(Foo1).Union.fields[0].field_type{ .x = 123 }, @@ -473,8 +476,11 @@ test "update the tag value for zero-sized unions" { } test "union initializer generates padding only if needed" { + if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; + if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; + if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO const U = union(enum) { A: u24, @@ -747,9 +753,11 @@ fn Setter(attr: Attribute) type { } test "return union init with void payload" { + if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; + if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO const S = struct { fn entry() !void { @@ -775,6 +783,7 @@ test "@unionInit stored to a const" { if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO const S = struct { const U = union(enum) { @@ -937,6 +946,7 @@ test "cast from anonymous struct to union" { if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO const S = struct { const U = union(enum) { @@ -969,6 +979,7 @@ test "cast from pointer to anonymous struct to pointer to union" { if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO const S = struct { const U = union(enum) { @@ -1104,6 +1115,8 @@ test "union enum type gets a separate scope" { test "global variable struct contains union initialized to non-most-aligned field" { if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO const T = struct { const U = union(enum) { diff --git a/test/cases/compile_errors/wrong_initializer_for_union_payload_of_type_type.zig b/test/cases/compile_errors/wrong_initializer_for_union_payload_of_type_type.zig index dd69531b01..03f7ad0a8f 100644 --- a/test/cases/compile_errors/wrong_initializer_for_union_payload_of_type_type.zig +++ b/test/cases/compile_errors/wrong_initializer_for_union_payload_of_type_type.zig @@ -13,5 +13,4 @@ export fn entry() void { // backend=stage2 // target=native // -// :9:14: error: expected type 'type', found 'tmp.U' -// :1:11: note: union declared here +// :9:8: error: use of undefined value here causes undefined behavior diff --git a/test/cases/safety/bad union field access.zig b/test/cases/safety/bad union field access.zig index 7adf48abf2..bdde8d9f3a 100644 --- a/test/cases/safety/bad union field access.zig +++ b/test/cases/safety/bad union field access.zig @@ -1,9 +1,11 @@ const std = @import("std"); pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn { - _ = message; _ = stack_trace; - std.process.exit(0); + if (std.mem.eql(u8, message, "access of inactive union field")) { + std.process.exit(0); + } + std.process.exit(1); } const Foo = union { @@ -21,5 +23,5 @@ fn bar(f: *Foo) void { f.float = 12.34; } // run -// backend=stage1 -// target=native \ No newline at end of file +// backend=llvm +// target=native -- cgit v1.2.3