From db1819e8ed02d3bb230b82f875b45fe7a6274c49 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Sat, 3 Dec 2022 02:59:02 -0800 Subject: [PATCH] CBE: fix use-after-free of Type keys in free_locals map --- src/codegen/c.zig | 17 ++++++++++++----- src/link/C.zig | 1 + 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() };