Skip to content

Commit

Permalink
Sema: prevent comptime-mutable pointers leaking into runtime code
Browse files Browse the repository at this point in the history
Resolves: ziglang#10920
  • Loading branch information
mlugg committed Mar 17, 2023
1 parent 68c7261 commit a012a3b
Show file tree
Hide file tree
Showing 2 changed files with 76 additions and 0 deletions.
28 changes: 28 additions & 0 deletions src/Sema.zig
Original file line number Diff line number Diff line change
Expand Up @@ -7087,6 +7087,9 @@ fn analyzeCallArg(
opts: CoerceOpts,
) !Air.Inst.Ref {
try sema.resolveTypeFully(param_ty);
if (try sema.resolveMaybeUndefVal(uncasted_arg)) |arg_val| {
try sema.checkValueDoesNotReferenceComptimeMutableMemory(block, arg_val, arg_src);
}
return sema.coerceExtra(block, param_ty, uncasted_arg, arg_src, opts) catch |err| switch (err) {
error.NotCoercible => unreachable,
else => |e| return e,
Expand All @@ -7107,6 +7110,9 @@ fn analyzeGenericCallArg(
comptime_arg.ty.hasRuntimeBits() and
!(try sema.typeRequiresComptime(comptime_arg.ty));
if (is_runtime) {
if (try sema.resolveMaybeUndefVal(uncasted_arg)) |arg_val| {
try sema.checkValueDoesNotReferenceComptimeMutableMemory(block, arg_val, arg_src);
}
const param_ty = new_fn_info.param_types[runtime_i.*];
const casted_arg = try sema.coerce(block, param_ty, uncasted_arg, arg_src);
try sema.queueFullTypeResolution(param_ty);
Expand Down Expand Up @@ -20425,6 +20431,23 @@ fn checkPtrIsNotComptimeMutable(
}
}

fn checkValueDoesNotReferenceComptimeMutableMemory(
sema: *Sema,
block: *Block,
val: Value,
src: LazySrcLoc,
) CompileError!void {
if (val.canMutateComptimeVarState()) {
const msg = msg: {
const msg = try sema.errMsg(block, src, "cannot store reference to comptime-mutable state at runtime", .{});
errdefer msg.destroy(sema.gpa);
try sema.errNote(block, src, msg, "copy comptime data to a const to use it at runtime", .{});
break :msg msg;
};
return sema.failWithOwnedErrorMsg(msg);
}
}

fn checkComptimeVarStore(
sema: *Sema,
block: *Block,
Expand Down Expand Up @@ -26441,6 +26464,11 @@ fn storePtr2(
} else break :rs ptr_src;
} else ptr_src;

if (maybe_operand_val) |operand_val| {
// Note that ptr's target is not comptime-mutable by the above check
try sema.checkValueDoesNotReferenceComptimeMutableMemory(block, operand_val, operand_src);
}

// We do this after the possible comptime store above, for the case of field_ptr stores
// to unions because we want the comptime tag to be set, even if the field type is void.
if ((try sema.typeHasOnePossibleValue(elem_ty)) != null)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
var ptr0: *const u32 = undefined;
export fn a() void {
comptime var x: u32 = 42;
ptr0 = &x;
}

export fn b() void {
comptime var x: u32 = 42;
var ptr1: *const u32 = &x;
_ = ptr1;
}

export fn c() void {
comptime var x: u32 = 42;
normalFunc(&x);
}
fn normalFunc(_: *const u32) void {}

export fn d() void {
comptime var x: u32 = 42;
genericFunc(0, &x);
}
fn genericFunc(comptime _: u8, _: *const u32) void {}

export fn e() void {
comptime var x: u32 = 42;
genericFuncGood(&x);
}
fn genericFuncGood(comptime _: *const u32) void {}

export fn f() void {
comptime var x: u32 = 42;
inlineGood(&x);
}
inline fn inlineGood(_: *const u32) void {}

// error
// backend=stage2
// target=native
//
// :4:12: error: cannot store reference to comptime-mutable state at runtime
// :4:12: note: copy comptime data to a const to use it at runtime
// :9:28: error: cannot store reference to comptime-mutable state at runtime
// :9:28: note: copy comptime data to a const to use it at runtime
// :15:16: error: cannot store reference to comptime-mutable state at runtime
// :15:16: note: copy comptime data to a const to use it at runtime
// :21:20: error: cannot store reference to comptime-mutable state at runtime
// :21:20: note: copy comptime data to a const to use it at runtime

0 comments on commit a012a3b

Please sign in to comment.