Skip to content

Commit

Permalink
CBE: fix use-after-free of Type keys in free_locals map
Browse files Browse the repository at this point in the history
  • Loading branch information
andrewrk committed Dec 4, 2022
1 parent 7bd63a6 commit db1819e
Show file tree
Hide file tree
Showing 2 changed files with 13 additions and 5 deletions.
17 changes: 12 additions & 5 deletions src/codegen/c.zig
Original file line number Diff line number Diff line change
Expand Up @@ -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 };
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -420,6 +422,7 @@ pub const Function = struct {
}
f.object.dg.typedefs.deinit();
f.object.dg.fwd_decl.deinit();
f.arena.deinit();
}
};

Expand Down Expand Up @@ -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(", ");
Expand All @@ -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) {
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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);
Expand Down
1 change: 1 addition & 0 deletions src/link/C.zig
Original file line number Diff line number Diff line change
Expand Up @@ -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() };
Expand Down

0 comments on commit db1819e

Please sign in to comment.