Skip to content

Commit f46d730

Browse files
committed
stage2: add runtime safety for invalid enum values
1 parent 19d5ffc commit f46d730

File tree

15 files changed

+131
-7
lines changed

15 files changed

+131
-7
lines changed

src/Air.zig

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -660,6 +660,10 @@ pub const Inst = struct {
660660
/// Uses the `pl_op` field with payload `AtomicRmw`. Operand is `ptr`.
661661
atomic_rmw,
662662

663+
/// Returns true if enum tag value has a name.
664+
/// Uses the `un_op` field.
665+
is_named_enum_value,
666+
663667
/// Given an enum tag value, returns the tag name. The enum type may be non-exhaustive.
664668
/// Result type is always `[:0]const u8`.
665669
/// Uses the `un_op` field.
@@ -1057,6 +1061,7 @@ pub fn typeOfIndex(air: Air, inst: Air.Inst.Index) Type {
10571061
.is_non_err,
10581062
.is_err_ptr,
10591063
.is_non_err_ptr,
1064+
.is_named_enum_value,
10601065
=> return Type.bool,
10611066

10621067
.const_ty => return Type.type,

src/Liveness.zig

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -291,6 +291,7 @@ pub fn categorizeOperand(
291291
.is_non_err_ptr,
292292
.ptrtoint,
293293
.bool_to_int,
294+
.is_named_enum_value,
294295
.tag_name,
295296
.error_name,
296297
.sqrt,
@@ -858,6 +859,7 @@ fn analyzeInst(
858859
.bool_to_int,
859860
.ret,
860861
.ret_load,
862+
.is_named_enum_value,
861863
.tag_name,
862864
.error_name,
863865
.sqrt,

src/Sema.zig

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6933,8 +6933,12 @@ fn zirIntToEnum(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
69336933
}
69346934

69356935
try sema.requireRuntimeBlock(block, src, operand_src);
6936-
// TODO insert safety check to make sure the value matches an enum value
6937-
return block.addTyOp(.intcast, dest_ty, operand);
6936+
const result = try block.addTyOp(.intcast, dest_ty, operand);
6937+
if (block.wantSafety() and !dest_ty.isNonexhaustiveEnum() and sema.mod.comp.bin_file.options.use_llvm) {
6938+
const ok = try block.addUnOp(.is_named_enum_value, result);
6939+
try sema.addSafetyCheck(block, ok, .invalid_enum_value);
6940+
}
6941+
return result;
69386942
}
69396943

69406944
/// Pointer in, pointer out.
@@ -15887,6 +15891,11 @@ fn zirTagName(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
1588715891
const field_name = enum_ty.enumFieldName(field_index);
1588815892
return sema.addStrLit(block, field_name);
1588915893
}
15894+
try sema.requireRuntimeBlock(block, src, operand_src);
15895+
if (block.wantSafety() and sema.mod.comp.bin_file.options.use_llvm) {
15896+
const ok = try block.addUnOp(.is_named_enum_value, casted_operand);
15897+
try sema.addSafetyCheck(block, ok, .invalid_enum_value);
15898+
}
1589015899
// In case the value is runtime-known, we have an AIR instruction for this instead
1589115900
// of trying to lower it in Sema because an optimization pass may result in the operand
1589215901
// being comptime-known, which would let us elide the `tag_name` AIR instruction.
@@ -20019,6 +20028,7 @@ pub const PanicId = enum {
2001920028
integer_part_out_of_bounds,
2002020029
corrupt_switch,
2002120030
shift_rhs_too_big,
20031+
invalid_enum_value,
2002220032
};
2002320033

2002420034
fn addSafetyCheck(
@@ -20316,6 +20326,7 @@ fn safetyPanic(
2031620326
.integer_part_out_of_bounds => "integer part of floating point value out of bounds",
2031720327
.corrupt_switch => "switch on corrupt value",
2031820328
.shift_rhs_too_big => "shift amount is greater than the type size",
20329+
.invalid_enum_value => "invalid enum value",
2031920330
};
2032020331

2032120332
const msg_inst = msg_inst: {

src/arch/aarch64/CodeGen.zig

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -753,6 +753,8 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
753753
.float_to_int_optimized,
754754
=> return self.fail("TODO implement optimized float mode", .{}),
755755

756+
.is_named_enum_value => return self.fail("TODO implement is_named_enum_value", .{}),
757+
756758
.wasm_memory_size => unreachable,
757759
.wasm_memory_grow => unreachable,
758760
// zig fmt: on

src/arch/arm/CodeGen.zig

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -768,6 +768,8 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
768768
.float_to_int_optimized,
769769
=> return self.fail("TODO implement optimized float mode", .{}),
770770

771+
.is_named_enum_value => return self.fail("TODO implement is_named_enum_value", .{}),
772+
771773
.wasm_memory_size => unreachable,
772774
.wasm_memory_grow => unreachable,
773775
// zig fmt: on

src/arch/riscv64/CodeGen.zig

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -693,6 +693,8 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
693693
.float_to_int_optimized,
694694
=> return self.fail("TODO implement optimized float mode", .{}),
695695

696+
.is_named_enum_value => return self.fail("TODO implement is_named_enum_value", .{}),
697+
696698
.wasm_memory_size => unreachable,
697699
.wasm_memory_grow => unreachable,
698700
// zig fmt: on

src/arch/sparc64/CodeGen.zig

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -705,6 +705,8 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
705705
.float_to_int_optimized,
706706
=> @panic("TODO implement optimized float mode"),
707707

708+
.is_named_enum_value => @panic("TODO implement is_named_enum_value"),
709+
708710
.wasm_memory_size => unreachable,
709711
.wasm_memory_grow => unreachable,
710712
// zig fmt: on

src/arch/wasm/CodeGen.zig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1621,6 +1621,7 @@ fn genInst(self: *Self, inst: Air.Inst.Index) !WValue {
16211621
.tag_name,
16221622
.err_return_trace,
16231623
.set_err_return_trace,
1624+
.is_named_enum_value,
16241625
=> |tag| return self.fail("TODO: Implement wasm inst: {s}", .{@tagName(tag)}),
16251626

16261627
.add_optimized,

src/arch/x86_64/CodeGen.zig

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -775,6 +775,8 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
775775
.float_to_int_optimized,
776776
=> return self.fail("TODO implement optimized float mode", .{}),
777777

778+
.is_named_enum_value => return self.fail("TODO implement is_named_enum_value", .{}),
779+
778780
.wasm_memory_size => unreachable,
779781
.wasm_memory_grow => unreachable,
780782
// zig fmt: on

src/codegen/c.zig

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1952,6 +1952,8 @@ fn genBody(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, OutO
19521952
.reduce_optimized,
19531953
.float_to_int_optimized,
19541954
=> return f.fail("TODO implement optimized float mode", .{}),
1955+
1956+
.is_named_enum_value => return f.fail("TODO: C backend: implement is_named_enum_value", .{}),
19551957
// zig fmt: on
19561958
};
19571959
switch (result_value) {

0 commit comments

Comments
 (0)