mirror of
https://github.com/ziglang/zig.git
synced 2026-02-21 16:54:52 +00:00
link: Coff, MachO, and Wasm all had the same UAF bug
This commit is contained in:
parent
098a07dc45
commit
cf9735a5e0
@ -1737,46 +1737,51 @@ pub fn getDeclVAddr(self: *Coff, decl_index: Module.Decl.Index, reloc_info: link
|
||||
return 0;
|
||||
}
|
||||
|
||||
pub fn lowerAnonDecl(self: *Coff, decl_val: InternPool.Index, decl_align: InternPool.Alignment, src_loc: Module.SrcLoc) !codegen.Result {
|
||||
// This is basically the same as lowerUnnamedConst.
|
||||
// example:
|
||||
// const ty = mod.intern_pool.typeOf(decl_val).toType();
|
||||
// const val = decl_val.toValue();
|
||||
// The symbol name can be something like `__anon_{d}` with `@intFromEnum(decl_val)`.
|
||||
// It doesn't have an owner decl because it's just an unnamed constant that might
|
||||
// be used by more than one function, however, its address is being used so we need
|
||||
// to put it in some location.
|
||||
// ...
|
||||
pub fn lowerAnonDecl(
|
||||
self: *Coff,
|
||||
decl_val: InternPool.Index,
|
||||
explicit_alignment: InternPool.Alignment,
|
||||
src_loc: Module.SrcLoc,
|
||||
) !codegen.Result {
|
||||
const gpa = self.base.allocator;
|
||||
const mod = self.base.options.module.?;
|
||||
const ty = mod.intern_pool.typeOf(decl_val).toType();
|
||||
const gop = try self.anon_decls.getOrPut(gpa, decl_val);
|
||||
const required_alignment = switch (decl_align) {
|
||||
const decl_alignment = switch (explicit_alignment) {
|
||||
.none => ty.abiAlignment(mod),
|
||||
else => decl_align,
|
||||
else => explicit_alignment,
|
||||
};
|
||||
if (!gop.found_existing or
|
||||
!required_alignment.check(self.getAtom(gop.value_ptr.*).getSymbol(self).value))
|
||||
{
|
||||
const val = decl_val.toValue();
|
||||
const tv = TypedValue{ .ty = ty, .val = val };
|
||||
const name = try std.fmt.allocPrint(gpa, "__anon_{d}", .{@intFromEnum(decl_val)});
|
||||
defer gpa.free(name);
|
||||
const res = self.lowerConst(name, tv, required_alignment, self.rdata_section_index.?, src_loc) catch |err| switch (err) {
|
||||
else => {
|
||||
// TODO improve error message
|
||||
const em = try Module.ErrorMsg.create(gpa, src_loc, "lowerAnonDecl failed with error: {s}", .{
|
||||
@errorName(err),
|
||||
});
|
||||
return .{ .fail = em };
|
||||
},
|
||||
};
|
||||
const atom_index = switch (res) {
|
||||
.ok => |atom_index| atom_index,
|
||||
.fail => |em| return .{ .fail = em },
|
||||
};
|
||||
gop.value_ptr.* = atom_index;
|
||||
if (self.anon_decls.get(decl_val)) |atom_index| {
|
||||
const existing_addr = self.getAtom(atom_index).getSymbol(self).value;
|
||||
if (decl_alignment.check(existing_addr))
|
||||
return .ok;
|
||||
}
|
||||
|
||||
const val = decl_val.toValue();
|
||||
const tv = TypedValue{ .ty = ty, .val = val };
|
||||
var name_buf: [32]u8 = undefined;
|
||||
const name = std.fmt.bufPrint(&name_buf, "__anon_{d}", .{
|
||||
@intFromEnum(decl_val),
|
||||
}) catch unreachable;
|
||||
const res = self.lowerConst(
|
||||
name,
|
||||
tv,
|
||||
decl_alignment,
|
||||
self.rdata_section_index.?,
|
||||
src_loc,
|
||||
) catch |err| switch (err) {
|
||||
error.OutOfMemory => return error.OutOfMemory,
|
||||
else => |e| return .{ .fail = try Module.ErrorMsg.create(
|
||||
gpa,
|
||||
src_loc,
|
||||
"lowerAnonDecl failed with error: {s}",
|
||||
.{@errorName(e)},
|
||||
) },
|
||||
};
|
||||
const atom_index = switch (res) {
|
||||
.ok => |atom_index| atom_index,
|
||||
.fail => |em| return .{ .fail = em },
|
||||
};
|
||||
try self.anon_decls.put(gpa, decl_val, atom_index);
|
||||
return .ok;
|
||||
}
|
||||
|
||||
|
||||
@ -2866,46 +2866,51 @@ pub fn getDeclVAddr(self: *MachO, decl_index: Module.Decl.Index, reloc_info: Fil
|
||||
return 0;
|
||||
}
|
||||
|
||||
pub fn lowerAnonDecl(self: *MachO, decl_val: InternPool.Index, decl_align: InternPool.Alignment, src_loc: Module.SrcLoc) !codegen.Result {
|
||||
// This is basically the same as lowerUnnamedConst.
|
||||
// example:
|
||||
// const ty = mod.intern_pool.typeOf(decl_val).toType();
|
||||
// const val = decl_val.toValue();
|
||||
// The symbol name can be something like `__anon_{d}` with `@intFromEnum(decl_val)`.
|
||||
// It doesn't have an owner decl because it's just an unnamed constant that might
|
||||
// be used by more than one function, however, its address is being used so we need
|
||||
// to put it in some location.
|
||||
// ...
|
||||
pub fn lowerAnonDecl(
|
||||
self: *MachO,
|
||||
decl_val: InternPool.Index,
|
||||
explicit_alignment: InternPool.Alignment,
|
||||
src_loc: Module.SrcLoc,
|
||||
) !codegen.Result {
|
||||
const gpa = self.base.allocator;
|
||||
const mod = self.base.options.module.?;
|
||||
const ty = mod.intern_pool.typeOf(decl_val).toType();
|
||||
const gop = try self.anon_decls.getOrPut(gpa, decl_val);
|
||||
const required_alignment = switch (decl_align) {
|
||||
const decl_alignment = switch (explicit_alignment) {
|
||||
.none => ty.abiAlignment(mod),
|
||||
else => decl_align,
|
||||
else => explicit_alignment,
|
||||
};
|
||||
if (!gop.found_existing or
|
||||
!required_alignment.check(self.getAtom(gop.value_ptr.*).getSymbol(self).n_value))
|
||||
{
|
||||
const val = decl_val.toValue();
|
||||
const tv = TypedValue{ .ty = ty, .val = val };
|
||||
const name = try std.fmt.allocPrint(gpa, "__anon_{d}", .{@intFromEnum(decl_val)});
|
||||
defer gpa.free(name);
|
||||
const res = self.lowerConst(name, tv, required_alignment, self.data_const_section_index.?, src_loc) catch |err| switch (err) {
|
||||
else => {
|
||||
// TODO improve error message
|
||||
const em = try Module.ErrorMsg.create(gpa, src_loc, "lowerAnonDecl failed with error: {s}", .{
|
||||
@errorName(err),
|
||||
});
|
||||
return .{ .fail = em };
|
||||
},
|
||||
};
|
||||
const atom_index = switch (res) {
|
||||
.ok => |atom_index| atom_index,
|
||||
.fail => |em| return .{ .fail = em },
|
||||
};
|
||||
gop.value_ptr.* = atom_index;
|
||||
if (self.anon_decls.get(decl_val)) |atom_index| {
|
||||
const existing_addr = self.getAtom(atom_index).getSymbol(self).n_value;
|
||||
if (decl_alignment.check(existing_addr))
|
||||
return .ok;
|
||||
}
|
||||
|
||||
const val = decl_val.toValue();
|
||||
const tv = TypedValue{ .ty = ty, .val = val };
|
||||
var name_buf: [32]u8 = undefined;
|
||||
const name = std.fmt.bufPrint(&name_buf, "__anon_{d}", .{
|
||||
@intFromEnum(decl_val),
|
||||
}) catch unreachable;
|
||||
const res = self.lowerConst(
|
||||
name,
|
||||
tv,
|
||||
decl_alignment,
|
||||
self.data_const_section_index.?,
|
||||
src_loc,
|
||||
) catch |err| switch (err) {
|
||||
error.OutOfMemory => return error.OutOfMemory,
|
||||
else => |e| return .{ .fail = try Module.ErrorMsg.create(
|
||||
gpa,
|
||||
src_loc,
|
||||
"unable to lower constant value: {s}",
|
||||
.{@errorName(e)},
|
||||
) },
|
||||
};
|
||||
const atom_index = switch (res) {
|
||||
.ok => |atom_index| atom_index,
|
||||
.fail => |em| return .{ .fail = em },
|
||||
};
|
||||
try self.anon_decls.put(gpa, decl_val, atom_index);
|
||||
return .ok;
|
||||
}
|
||||
|
||||
|
||||
@ -1702,27 +1702,34 @@ pub fn getDeclVAddr(
|
||||
return target_symbol_index;
|
||||
}
|
||||
|
||||
pub fn lowerAnonDecl(wasm: *Wasm, decl_val: InternPool.Index, decl_align: Alignment, src_loc: Module.SrcLoc) !codegen.Result {
|
||||
pub fn lowerAnonDecl(
|
||||
wasm: *Wasm,
|
||||
decl_val: InternPool.Index,
|
||||
explicit_alignment: Alignment,
|
||||
src_loc: Module.SrcLoc,
|
||||
) !codegen.Result {
|
||||
const gop = try wasm.anon_decls.getOrPut(wasm.base.allocator, decl_val);
|
||||
if (!gop.found_existing) {
|
||||
const mod = wasm.base.options.module.?;
|
||||
const ty = mod.intern_pool.typeOf(decl_val).toType();
|
||||
const tv: TypedValue = .{ .ty = ty, .val = decl_val.toValue() };
|
||||
const name = try std.fmt.allocPrintZ(wasm.base.allocator, "__anon_{d}", .{@intFromEnum(decl_val)});
|
||||
defer wasm.base.allocator.free(name);
|
||||
var name_buf: [32]u8 = undefined;
|
||||
const name = std.fmt.bufPrint(&name_buf, "__anon_{d}", .{
|
||||
@intFromEnum(decl_val),
|
||||
}) catch unreachable;
|
||||
|
||||
switch (try wasm.lowerConst(name, tv, src_loc)) {
|
||||
.ok => |atom_index| gop.value_ptr.* = atom_index,
|
||||
.ok => |atom_index| wasm.anon_decls.values()[gop.index] = atom_index,
|
||||
.fail => |em| return .{ .fail = em },
|
||||
}
|
||||
}
|
||||
|
||||
const atom = wasm.getAtomPtr(gop.value_ptr.*);
|
||||
const atom = wasm.getAtomPtr(wasm.anon_decls.values()[gop.index]);
|
||||
atom.alignment = switch (atom.alignment) {
|
||||
.none => decl_align,
|
||||
else => switch (decl_align) {
|
||||
.none => explicit_alignment,
|
||||
else => switch (explicit_alignment) {
|
||||
.none => atom.alignment,
|
||||
else => atom.alignment.maxStrict(decl_align),
|
||||
else => atom.alignment.maxStrict(explicit_alignment),
|
||||
},
|
||||
};
|
||||
return .ok;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user