aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormlugg <mlugg@mlugg.co.uk>2023-06-02 01:55:16 +0100
committerAndrew Kelley <andrew@ziglang.org>2023-06-10 20:47:58 -0700
commite0179640d54f4a61aa7522ac8529d36769fb9c08 (patch)
tree3bcd901567fea1e9206e1323411a65b22cfcfeed
parente8bcdca044603fb5ea93fc94028dfd8bdd22fcf3 (diff)
downloadzig-e0179640d54f4a61aa7522ac8529d36769fb9c08.tar.gz
zig-e0179640d54f4a61aa7522ac8529d36769fb9c08.zip
Sema: intern values of mutable decls after analysis
This is necessary with the upcoming removal of Decl.value_arena to prevent UAF of these values.
-rw-r--r--src/Module.zig24
-rw-r--r--src/Sema.zig51
2 files changed, 74 insertions, 1 deletions
diff --git a/src/Module.zig b/src/Module.zig
index 06e8c53eb7..d575f89b41 100644
--- a/src/Module.zig
+++ b/src/Module.zig
@@ -4424,6 +4424,9 @@ pub fn semaFile(mod: *Module, file: *File) SemaError!void {
defer sema_arena.deinit();
const sema_arena_allocator = sema_arena.allocator();
+ var comptime_mutable_decls = std.ArrayList(Decl.Index).init(gpa);
+ defer comptime_mutable_decls.deinit();
+
var sema: Sema = .{
.mod = mod,
.gpa = gpa,
@@ -4437,6 +4440,7 @@ pub fn semaFile(mod: *Module, file: *File) SemaError!void {
.fn_ret_ty = Type.void,
.owner_func = null,
.owner_func_index = .none,
+ .comptime_mutable_decls = &comptime_mutable_decls,
};
defer sema.deinit();
@@ -4445,6 +4449,10 @@ pub fn semaFile(mod: *Module, file: *File) SemaError!void {
if (sema.analyzeStructDecl(new_decl, main_struct_inst, struct_index)) |_| {
try wip_captures.finalize();
+ for (comptime_mutable_decls.items) |decl_index| {
+ const decl = mod.declPtr(decl_index);
+ try decl.intern(mod);
+ }
new_decl.analysis = .complete;
} else |err| switch (err) {
error.OutOfMemory => return error.OutOfMemory,
@@ -4522,6 +4530,9 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool {
defer analysis_arena.deinit();
const analysis_arena_allocator = analysis_arena.allocator();
+ var comptime_mutable_decls = std.ArrayList(Decl.Index).init(gpa);
+ defer comptime_mutable_decls.deinit();
+
var sema: Sema = .{
.mod = mod,
.gpa = gpa,
@@ -4535,6 +4546,7 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool {
.fn_ret_ty = Type.void,
.owner_func = null,
.owner_func_index = .none,
+ .comptime_mutable_decls = &comptime_mutable_decls,
};
defer sema.deinit();
@@ -4577,6 +4589,10 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool {
const body = zir.extra[extra.end..][0..extra.data.body_len];
const result_ref = (try sema.analyzeBodyBreak(&block_scope, body)).?.operand;
try wip_captures.finalize();
+ for (comptime_mutable_decls.items) |ct_decl_index| {
+ const ct_decl = mod.declPtr(ct_decl_index);
+ try ct_decl.intern(mod);
+ }
const align_src: LazySrcLoc = .{ .node_offset_var_decl_align = 0 };
const section_src: LazySrcLoc = .{ .node_offset_var_decl_section = 0 };
const address_space_src: LazySrcLoc = .{ .node_offset_var_decl_addrspace = 0 };
@@ -5486,6 +5502,9 @@ pub fn analyzeFnBody(mod: *Module, func_index: Fn.Index, arena: Allocator) SemaE
const decl_arena_allocator = decl.value_arena.?.acquire(gpa, &decl_arena);
defer decl.value_arena.?.release(&decl_arena);
+ var comptime_mutable_decls = std.ArrayList(Decl.Index).init(gpa);
+ defer comptime_mutable_decls.deinit();
+
const fn_ty = decl.ty;
const fn_ty_info = mod.typeToFunc(fn_ty).?;
@@ -5503,6 +5522,7 @@ pub fn analyzeFnBody(mod: *Module, func_index: Fn.Index, arena: Allocator) SemaE
.owner_func = func,
.owner_func_index = func_index.toOptional(),
.branch_quota = @max(func.branch_quota, Sema.default_branch_quota),
+ .comptime_mutable_decls = &comptime_mutable_decls,
};
defer sema.deinit();
@@ -5642,6 +5662,10 @@ pub fn analyzeFnBody(mod: *Module, func_index: Fn.Index, arena: Allocator) SemaE
}
try wip_captures.finalize();
+ for (comptime_mutable_decls.items) |ct_decl_index| {
+ const ct_decl = mod.declPtr(ct_decl_index);
+ try ct_decl.intern(mod);
+ }
// Copy the block into place and mark that as the main block.
try sema.air_extra.ensureUnusedCapacity(gpa, @typeInfo(Air.Block).Struct.fields.len +
diff --git a/src/Sema.zig b/src/Sema.zig
index 9b36ddb969..620a8a6a28 100644
--- a/src/Sema.zig
+++ b/src/Sema.zig
@@ -92,6 +92,14 @@ no_partial_func_ty: bool = false,
/// here so the values can be dropped without any cleanup.
unresolved_inferred_allocs: std.AutoHashMapUnmanaged(Air.Inst.Index, InferredAlloc) = .{},
+/// Indices of comptime-mutable decls created by this Sema. These decls' values
+/// should be interned after analysis completes, as they may refer to memory in
+/// the Sema arena.
+/// TODO: this is a workaround for memory bugs triggered by the removal of
+/// Decl.value_arena. A better solution needs to be found. Probably this will
+/// involve transitioning comptime-mutable memory away from using Decls at all.
+comptime_mutable_decls: *std.ArrayList(Decl.Index),
+
const std = @import("std");
const math = std.math;
const mem = std.mem;
@@ -2545,6 +2553,7 @@ fn zirCoerceResultPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE
},
});
try sema.maybeQueueFuncBodyAnalysis(decl_index);
+ try sema.comptime_mutable_decls.append(decl_index);
return sema.addConstant(ptr_ty, (try mod.intern(.{ .ptr = .{
.ty = ptr_ty.toIntern(),
.addr = .{ .mut_decl = .{
@@ -7761,6 +7770,7 @@ fn resolveGenericInstantiationType(
.is_generic_instantiation = true,
.branch_quota = sema.branch_quota,
.branch_count = sema.branch_count,
+ .comptime_mutable_decls = sema.comptime_mutable_decls,
};
defer child_sema.deinit();
@@ -31863,7 +31873,24 @@ fn semaBackingIntType(mod: *Module, struct_obj: *Module.Struct) CompileError!voi
var analysis_arena = std.heap.ArenaAllocator.init(gpa);
defer analysis_arena.deinit();
- var sema: Sema = .{ .mod = mod, .gpa = gpa, .arena = analysis_arena.allocator(), .perm_arena = decl_arena_allocator, .code = zir, .owner_decl = decl, .owner_decl_index = decl_index, .func = null, .func_index = .none, .fn_ret_ty = Type.void, .owner_func = null, .owner_func_index = .none };
+ var comptime_mutable_decls = std.ArrayList(Decl.Index).init(gpa);
+ defer comptime_mutable_decls.deinit();
+
+ var sema: Sema = .{
+ .mod = mod,
+ .gpa = gpa,
+ .arena = analysis_arena.allocator(),
+ .perm_arena = decl_arena_allocator,
+ .code = zir,
+ .owner_decl = decl,
+ .owner_decl_index = decl_index,
+ .func = null,
+ .func_index = .none,
+ .fn_ret_ty = Type.void,
+ .owner_func = null,
+ .owner_func_index = .none,
+ .comptime_mutable_decls = &comptime_mutable_decls,
+ };
defer sema.deinit();
var wip_captures = try WipCaptureScope.init(gpa, decl.src_scope);
@@ -31899,6 +31926,10 @@ fn semaBackingIntType(mod: *Module, struct_obj: *Module.Struct) CompileError!voi
try sema.checkBackingIntType(&block, backing_int_src, backing_int_ty, fields_bit_sum);
struct_obj.backing_int_ty = backing_int_ty;
try wip_captures.finalize();
+ for (comptime_mutable_decls.items) |ct_decl_index| {
+ const ct_decl = mod.declPtr(ct_decl_index);
+ try ct_decl.intern(mod);
+ }
} else {
if (fields_bit_sum > std.math.maxInt(u16)) {
var sema: Sema = .{
@@ -31914,6 +31945,7 @@ fn semaBackingIntType(mod: *Module, struct_obj: *Module.Struct) CompileError!voi
.fn_ret_ty = Type.void,
.owner_func = null,
.owner_func_index = .none,
+ .comptime_mutable_decls = undefined,
};
defer sema.deinit();
@@ -32603,6 +32635,9 @@ fn semaStructFields(mod: *Module, struct_obj: *Module.Struct) CompileError!void
var analysis_arena = std.heap.ArenaAllocator.init(gpa);
defer analysis_arena.deinit();
+ var comptime_mutable_decls = std.ArrayList(Decl.Index).init(gpa);
+ defer comptime_mutable_decls.deinit();
+
var sema: Sema = .{
.mod = mod,
.gpa = gpa,
@@ -32616,6 +32651,7 @@ fn semaStructFields(mod: *Module, struct_obj: *Module.Struct) CompileError!void
.fn_ret_ty = Type.void,
.owner_func = null,
.owner_func_index = .none,
+ .comptime_mutable_decls = &comptime_mutable_decls,
};
defer sema.deinit();
@@ -32886,6 +32922,10 @@ fn semaStructFields(mod: *Module, struct_obj: *Module.Struct) CompileError!void
}
}
try wip_captures.finalize();
+ for (comptime_mutable_decls.items) |ct_decl_index| {
+ const ct_decl = mod.declPtr(ct_decl_index);
+ try ct_decl.intern(mod);
+ }
struct_obj.have_field_inits = true;
}
@@ -32945,6 +32985,9 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void {
var analysis_arena = std.heap.ArenaAllocator.init(gpa);
defer analysis_arena.deinit();
+ var comptime_mutable_decls = std.ArrayList(Decl.Index).init(gpa);
+ defer comptime_mutable_decls.deinit();
+
var sema: Sema = .{
.mod = mod,
.gpa = gpa,
@@ -32958,6 +33001,7 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void {
.fn_ret_ty = Type.void,
.owner_func = null,
.owner_func_index = .none,
+ .comptime_mutable_decls = &comptime_mutable_decls,
};
defer sema.deinit();
@@ -32984,6 +33028,10 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void {
}
try wip_captures.finalize();
+ for (comptime_mutable_decls.items) |ct_decl_index| {
+ const ct_decl = mod.declPtr(ct_decl_index);
+ try ct_decl.intern(mod);
+ }
try union_obj.fields.ensureTotalCapacity(decl_arena_allocator, fields_len);
@@ -33821,6 +33869,7 @@ fn analyzeComptimeAlloc(
const decl = sema.mod.declPtr(decl_index);
decl.@"align" = alignment;
+ try sema.comptime_mutable_decls.append(decl_index);
try sema.mod.declareDeclDependency(sema.owner_decl_index, decl_index);
return sema.addConstant(ptr_type, (try sema.mod.intern(.{ .ptr = .{
.ty = ptr_type.toIntern(),