From 129ccad43443f26f00584816b18425c9a3a7b080 Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Sat, 7 Nov 2020 23:45:54 +0100 Subject: [PATCH] stage1: Reject undefined values when taking union ptr The code rightfully assumes the union_val object to be fully initialized. Closes #7019 --- src/stage1/ir.cpp | 11 +++++++++++ test/compile_errors.zig | 15 +++++++++++++++ 2 files changed, 26 insertions(+) diff --git a/src/stage1/ir.cpp b/src/stage1/ir.cpp index a513bd6ee8..1be9507480 100644 --- a/src/stage1/ir.cpp +++ b/src/stage1/ir.cpp @@ -22713,6 +22713,16 @@ static IrInstGen *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field_name if (type_is_invalid(union_val->type)) return ira->codegen->invalid_inst_gen; + // Reject undefined values unless we're intializing the union: + // a undefined union means also the tag is undefined, accessing + // its payload slot is UB. + const UndefAllowed allow_undef = initializing ? UndefOk : UndefBad; + if ((err = ir_resolve_const_val(ira->codegen, ira->new_irb.exec, + source_instr->source_node, union_val, allow_undef))) + { + return ira->codegen->invalid_inst_gen; + } + if (initializing) { ZigValue *payload_val = ira->codegen->pass1_arena->create(); payload_val->special = ConstValSpecialUndef; @@ -22737,6 +22747,7 @@ static IrInstGen *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field_name } ZigValue *payload_val = union_val->data.x_union.payload; + assert(payload_val); IrInstGen *result; if (ptr_val->data.x_ptr.mut == ConstPtrMutInfer) { diff --git a/test/compile_errors.zig b/test/compile_errors.zig index f81458ae8b..1d16cd6706 100644 --- a/test/compile_errors.zig +++ b/test/compile_errors.zig @@ -11,6 +11,21 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { "tmp.zig:1:50: error: use of undefined value here causes undefined behavior", }); + cases.add("wrong initializer for union payload of type 'type'", + \\const U = union(enum) { + \\ A: type, + \\}; + \\const S = struct { + \\ u: U, + \\}; + \\export fn entry() void { + \\ comptime var v: S = undefined; + \\ v.u.A = U{ .A = i32 }; + \\} + , &[_][]const u8{ + "tmp.zig:9:8: error: use of undefined value here causes undefined behavior", + }); + cases.add("union with too small explicit signed tag type", \\const U = union(enum(i2)) { \\ A: u8,