aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2022-12-03 02:59:02 -0800
committerAndrew Kelley <andrew@ziglang.org>2022-12-04 15:57:40 -0700
commitdb1819e8ed02d3bb230b82f875b45fe7a6274c49 (patch)
treeddc47479d455048dfa2dfd9c52833fcb5abcb258
parent7bd63a602a433044f321534117570b1da338e946 (diff)
downloadzig-db1819e8ed02d3bb230b82f875b45fe7a6274c49.tar.gz
zig-db1819e8ed02d3bb230b82f875b45fe7a6274c49.zip
CBE: fix use-after-free of Type keys in free_locals map
-rw-r--r--src/codegen/c.zig17
-rw-r--r--src/link/C.zig1
2 files changed, 13 insertions, 5 deletions
diff --git a/src/codegen/c.zig b/src/codegen/c.zig
index f66b7da6eb..14da51b276 100644
--- a/src/codegen/c.zig
+++ b/src/codegen/c.zig
@@ -272,6 +272,8 @@ pub const Function = struct {
/// variable declarations at the top of a function, sorted descending by
/// type alignment.
allocs: std.AutoArrayHashMapUnmanaged(LocalIndex, void) = .{},
+ /// Needed for memory used by Type objects used as keys in free_locals.
+ arena: std.heap.ArenaAllocator,
fn tyHashCtx(f: Function) Type.HashContext32 {
return .{ .mod = f.object.dg.module };
@@ -314,7 +316,7 @@ pub const Function = struct {
.ty = ty,
.alignment = alignment,
});
- return .{ .local = @intCast(LocalIndex, f.locals.items.len - 1) };
+ return CValue{ .local = @intCast(LocalIndex, f.locals.items.len - 1) };
}
fn allocLocal(f: *Function, inst: Air.Inst.Index, ty: Type) !CValue {
@@ -420,6 +422,7 @@ pub const Function = struct {
}
f.object.dg.typedefs.deinit();
f.object.dg.fwd_decl.deinit();
+ f.arena.deinit();
}
};
@@ -3228,8 +3231,9 @@ fn airRet(f: *Function, inst: Air.Inst.Index, is_ptr: bool) !CValue {
var deref = is_ptr;
const operand = try f.resolveInst(un_op);
try reap(f, inst, &.{un_op});
- const ret_val = if (lowersToArray(ret_ty, target)) ret_val: {
- const array_local = try f.allocLocal(inst, lowered_ret_ty);
+ const is_array = lowersToArray(ret_ty, target);
+ const ret_val = if (is_array) ret_val: {
+ const array_local = try f.allocLocal(inst, try lowered_ret_ty.copy(f.arena.allocator()));
try writer.writeAll("memcpy(");
try f.writeCValueMember(writer, array_local, .{ .field = 0 });
try writer.writeAll(", ");
@@ -3250,6 +3254,9 @@ fn airRet(f: *Function, inst: Air.Inst.Index, is_ptr: bool) !CValue {
else
try f.writeCValue(writer, ret_val, .Other);
try writer.writeAll(";\n");
+ if (is_array) {
+ try freeLocal(f, inst, ret_val.local, 0);
+ }
} else {
try reap(f, inst, &.{un_op});
if (f.object.dg.decl.ty.fnCallingConvention() != .Naked) {
@@ -3884,7 +3891,7 @@ fn airCall(
try writer.writeByte(')');
break :r .none;
} else r: {
- const local = try f.allocLocal(inst, lowered_ret_ty);
+ const local = try f.allocLocal(inst, try lowered_ret_ty.copy(f.arena.allocator()));
try f.writeCValue(writer, local, .Other);
try writer.writeAll(" = ");
break :r local;
@@ -5110,7 +5117,7 @@ fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue {
};
const field_int_ty = Type.initPayload(&field_int_pl.base);
- const temp_local = try f.allocLocal(inst, field_int_ty);
+ const temp_local = try f.allocLocal(inst, try field_int_ty.copy(f.arena.allocator()));
try f.writeCValue(writer, temp_local, .Other);
try writer.writeAll(" = zig_wrap_");
try f.object.dg.renderTypeForBuiltinFnName(writer, field_int_ty);
diff --git a/src/link/C.zig b/src/link/C.zig
index 880a3e154e..ad50a20b99 100644
--- a/src/link/C.zig
+++ b/src/link/C.zig
@@ -133,6 +133,7 @@ pub fn updateFunc(self: *C, module: *Module, func: *Module.Fn, air: Air, livenes
.code = code.toManaged(module.gpa),
.indent_writer = undefined, // set later so we can get a pointer to object.code
},
+ .arena = std.heap.ArenaAllocator.init(module.gpa),
};
function.object.indent_writer = .{ .underlying_writer = function.object.code.writer() };