InternPool: remove slice from byte aggregate keys
This deletes a ton of lookups and avoids many UAF bugs. Closes #19485
This commit is contained in:
107
src/codegen.zig
107
src/codegen.zig
@@ -97,7 +97,7 @@ fn writeFloat(comptime F: type, f: F, target: Target, endian: std.builtin.Endian
|
||||
_ = target;
|
||||
const bits = @typeInfo(F).Float.bits;
|
||||
const Int = @Type(.{ .Int = .{ .signedness = .unsigned, .bits = bits } });
|
||||
const int = @as(Int, @bitCast(f));
|
||||
const int: Int = @bitCast(f);
|
||||
mem.writeInt(Int, code[0..@divExact(bits, 8)], int, endian);
|
||||
}
|
||||
|
||||
@@ -136,24 +136,24 @@ pub fn generateLazySymbol(
|
||||
if (lazy_sym.ty.isAnyError(zcu)) {
|
||||
alignment.* = .@"4";
|
||||
const err_names = zcu.global_error_set.keys();
|
||||
mem.writeInt(u32, try code.addManyAsArray(4), @as(u32, @intCast(err_names.len)), endian);
|
||||
mem.writeInt(u32, try code.addManyAsArray(4), @intCast(err_names.len), endian);
|
||||
var offset = code.items.len;
|
||||
try code.resize((1 + err_names.len + 1) * 4);
|
||||
for (err_names) |err_name_nts| {
|
||||
const err_name = zcu.intern_pool.stringToSlice(err_name_nts);
|
||||
mem.writeInt(u32, code.items[offset..][0..4], @as(u32, @intCast(code.items.len)), endian);
|
||||
const err_name = err_name_nts.toSlice(ip);
|
||||
mem.writeInt(u32, code.items[offset..][0..4], @intCast(code.items.len), endian);
|
||||
offset += 4;
|
||||
try code.ensureUnusedCapacity(err_name.len + 1);
|
||||
code.appendSliceAssumeCapacity(err_name);
|
||||
code.appendAssumeCapacity(0);
|
||||
}
|
||||
mem.writeInt(u32, code.items[offset..][0..4], @as(u32, @intCast(code.items.len)), endian);
|
||||
mem.writeInt(u32, code.items[offset..][0..4], @intCast(code.items.len), endian);
|
||||
return Result.ok;
|
||||
} else if (lazy_sym.ty.zigTypeTag(zcu) == .Enum) {
|
||||
alignment.* = .@"1";
|
||||
const tag_names = lazy_sym.ty.enumFields(zcu);
|
||||
for (0..tag_names.len) |tag_index| {
|
||||
const tag_name = zcu.intern_pool.stringToSlice(tag_names.get(ip)[tag_index]);
|
||||
const tag_name = tag_names.get(ip)[tag_index].toSlice(ip);
|
||||
try code.ensureUnusedCapacity(tag_name.len + 1);
|
||||
code.appendSliceAssumeCapacity(tag_name);
|
||||
code.appendAssumeCapacity(0);
|
||||
@@ -241,13 +241,13 @@ pub fn generateSymbol(
|
||||
},
|
||||
.err => |err| {
|
||||
const int = try mod.getErrorValue(err.name);
|
||||
try code.writer().writeInt(u16, @as(u16, @intCast(int)), endian);
|
||||
try code.writer().writeInt(u16, @intCast(int), endian);
|
||||
},
|
||||
.error_union => |error_union| {
|
||||
const payload_ty = ty.errorUnionPayload(mod);
|
||||
const err_val = switch (error_union.val) {
|
||||
.err_name => |err_name| @as(u16, @intCast(try mod.getErrorValue(err_name))),
|
||||
.payload => @as(u16, 0),
|
||||
const err_val: u16 = switch (error_union.val) {
|
||||
.err_name => |err_name| @intCast(try mod.getErrorValue(err_name)),
|
||||
.payload => 0,
|
||||
};
|
||||
|
||||
if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) {
|
||||
@@ -357,15 +357,13 @@ pub fn generateSymbol(
|
||||
},
|
||||
.aggregate => |aggregate| switch (ip.indexToKey(ty.toIntern())) {
|
||||
.array_type => |array_type| switch (aggregate.storage) {
|
||||
.bytes => |bytes| try code.appendSlice(bytes),
|
||||
.bytes => |bytes| try code.appendSlice(bytes.toSlice(array_type.lenIncludingSentinel(), ip)),
|
||||
.elems, .repeated_elem => {
|
||||
var index: u64 = 0;
|
||||
const len_including_sentinel =
|
||||
array_type.len + @intFromBool(array_type.sentinel != .none);
|
||||
while (index < len_including_sentinel) : (index += 1) {
|
||||
while (index < array_type.lenIncludingSentinel()) : (index += 1) {
|
||||
switch (try generateSymbol(bin_file, src_loc, Value.fromInterned(switch (aggregate.storage) {
|
||||
.bytes => unreachable,
|
||||
.elems => |elems| elems[@as(usize, @intCast(index))],
|
||||
.elems => |elems| elems[@intCast(index)],
|
||||
.repeated_elem => |elem| if (index < array_type.len)
|
||||
elem
|
||||
else
|
||||
@@ -399,7 +397,7 @@ pub fn generateSymbol(
|
||||
}) {
|
||||
.bool_true => true,
|
||||
.bool_false => false,
|
||||
else => |elem| switch (mod.intern_pool.indexToKey(elem)) {
|
||||
else => |elem| switch (ip.indexToKey(elem)) {
|
||||
.undef => continue,
|
||||
.int => |int| switch (int.storage) {
|
||||
.u64 => |x| switch (x) {
|
||||
@@ -420,7 +418,7 @@ pub fn generateSymbol(
|
||||
}
|
||||
} else {
|
||||
switch (aggregate.storage) {
|
||||
.bytes => |bytes| try code.appendSlice(bytes),
|
||||
.bytes => |bytes| try code.appendSlice(bytes.toSlice(vector_type.len, ip)),
|
||||
.elems, .repeated_elem => {
|
||||
var index: u64 = 0;
|
||||
while (index < vector_type.len) : (index += 1) {
|
||||
@@ -457,7 +455,7 @@ pub fn generateSymbol(
|
||||
const field_val = switch (aggregate.storage) {
|
||||
.bytes => |bytes| try ip.get(mod.gpa, .{ .int = .{
|
||||
.ty = field_ty,
|
||||
.storage = .{ .u64 = bytes[index] },
|
||||
.storage = .{ .u64 = bytes.at(index, ip) },
|
||||
} }),
|
||||
.elems => |elems| elems[index],
|
||||
.repeated_elem => |elem| elem,
|
||||
@@ -493,7 +491,7 @@ pub fn generateSymbol(
|
||||
const field_val = switch (aggregate.storage) {
|
||||
.bytes => |bytes| try ip.get(mod.gpa, .{ .int = .{
|
||||
.ty = field_ty,
|
||||
.storage = .{ .u64 = bytes[index] },
|
||||
.storage = .{ .u64 = bytes.at(index, ip) },
|
||||
} }),
|
||||
.elems => |elems| elems[index],
|
||||
.repeated_elem => |elem| elem,
|
||||
@@ -513,7 +511,7 @@ pub fn generateSymbol(
|
||||
} else {
|
||||
Value.fromInterned(field_val).writeToPackedMemory(Type.fromInterned(field_ty), mod, code.items[current_pos..], bits) catch unreachable;
|
||||
}
|
||||
bits += @as(u16, @intCast(Type.fromInterned(field_ty).bitSize(mod)));
|
||||
bits += @intCast(Type.fromInterned(field_ty).bitSize(mod));
|
||||
}
|
||||
},
|
||||
.auto, .@"extern" => {
|
||||
@@ -529,7 +527,7 @@ pub fn generateSymbol(
|
||||
const field_val = switch (ip.indexToKey(val.toIntern()).aggregate.storage) {
|
||||
.bytes => |bytes| try ip.get(mod.gpa, .{ .int = .{
|
||||
.ty = field_ty,
|
||||
.storage = .{ .u64 = bytes[field_index] },
|
||||
.storage = .{ .u64 = bytes.at(field_index, ip) },
|
||||
} }),
|
||||
.elems => |elems| elems[field_index],
|
||||
.repeated_elem => |elem| elem,
|
||||
@@ -625,7 +623,8 @@ fn lowerParentPtr(
|
||||
reloc_info: RelocInfo,
|
||||
) CodeGenError!Result {
|
||||
const mod = bin_file.comp.module.?;
|
||||
const ptr = mod.intern_pool.indexToKey(parent_ptr).ptr;
|
||||
const ip = &mod.intern_pool;
|
||||
const ptr = ip.indexToKey(parent_ptr).ptr;
|
||||
return switch (ptr.addr) {
|
||||
.decl => |decl| try lowerDeclRef(bin_file, src_loc, decl, code, debug_output, reloc_info),
|
||||
.anon_decl => |ad| try lowerAnonDeclRef(bin_file, src_loc, ad, code, debug_output, reloc_info),
|
||||
@@ -636,10 +635,10 @@ fn lowerParentPtr(
|
||||
eu_payload,
|
||||
code,
|
||||
debug_output,
|
||||
reloc_info.offset(@as(u32, @intCast(errUnionPayloadOffset(
|
||||
Type.fromInterned(mod.intern_pool.typeOf(eu_payload)),
|
||||
reloc_info.offset(@intCast(errUnionPayloadOffset(
|
||||
Type.fromInterned(ip.typeOf(eu_payload)),
|
||||
mod,
|
||||
)))),
|
||||
))),
|
||||
),
|
||||
.opt_payload => |opt_payload| try lowerParentPtr(
|
||||
bin_file,
|
||||
@@ -655,19 +654,19 @@ fn lowerParentPtr(
|
||||
elem.base,
|
||||
code,
|
||||
debug_output,
|
||||
reloc_info.offset(@as(u32, @intCast(elem.index *
|
||||
Type.fromInterned(mod.intern_pool.typeOf(elem.base)).elemType2(mod).abiSize(mod)))),
|
||||
reloc_info.offset(@intCast(elem.index *
|
||||
Type.fromInterned(ip.typeOf(elem.base)).elemType2(mod).abiSize(mod))),
|
||||
),
|
||||
.field => |field| {
|
||||
const base_ptr_ty = mod.intern_pool.typeOf(field.base);
|
||||
const base_ty = mod.intern_pool.indexToKey(base_ptr_ty).ptr_type.child;
|
||||
const base_ptr_ty = ip.typeOf(field.base);
|
||||
const base_ty = ip.indexToKey(base_ptr_ty).ptr_type.child;
|
||||
return lowerParentPtr(
|
||||
bin_file,
|
||||
src_loc,
|
||||
field.base,
|
||||
code,
|
||||
debug_output,
|
||||
reloc_info.offset(switch (mod.intern_pool.indexToKey(base_ty)) {
|
||||
reloc_info.offset(switch (ip.indexToKey(base_ty)) {
|
||||
.ptr_type => |ptr_type| switch (ptr_type.flags.size) {
|
||||
.One, .Many, .C => unreachable,
|
||||
.Slice => switch (field.index) {
|
||||
@@ -723,11 +722,12 @@ fn lowerAnonDeclRef(
|
||||
) CodeGenError!Result {
|
||||
_ = debug_output;
|
||||
const zcu = lf.comp.module.?;
|
||||
const ip = &zcu.intern_pool;
|
||||
const target = lf.comp.root_mod.resolved_target.result;
|
||||
|
||||
const ptr_width_bytes = @divExact(target.ptrBitWidth(), 8);
|
||||
const decl_val = anon_decl.val;
|
||||
const decl_ty = Type.fromInterned(zcu.intern_pool.typeOf(decl_val));
|
||||
const decl_ty = Type.fromInterned(ip.typeOf(decl_val));
|
||||
log.debug("lowerAnonDecl: ty = {}", .{decl_ty.fmt(zcu)});
|
||||
const is_fn_body = decl_ty.zigTypeTag(zcu) == .Fn;
|
||||
if (!is_fn_body and !decl_ty.hasRuntimeBits(zcu)) {
|
||||
@@ -735,7 +735,7 @@ fn lowerAnonDeclRef(
|
||||
return Result.ok;
|
||||
}
|
||||
|
||||
const decl_align = zcu.intern_pool.indexToKey(anon_decl.orig_ty).ptr_type.flags.alignment;
|
||||
const decl_align = ip.indexToKey(anon_decl.orig_ty).ptr_type.flags.alignment;
|
||||
const res = try lf.lowerAnonDecl(decl_val, decl_align, src_loc);
|
||||
switch (res) {
|
||||
.ok => {},
|
||||
@@ -787,8 +787,8 @@ fn lowerDeclRef(
|
||||
});
|
||||
const endian = target.cpu.arch.endian();
|
||||
switch (ptr_width) {
|
||||
16 => mem.writeInt(u16, try code.addManyAsArray(2), @as(u16, @intCast(vaddr)), endian),
|
||||
32 => mem.writeInt(u32, try code.addManyAsArray(4), @as(u32, @intCast(vaddr)), endian),
|
||||
16 => mem.writeInt(u16, try code.addManyAsArray(2), @intCast(vaddr), endian),
|
||||
32 => mem.writeInt(u32, try code.addManyAsArray(4), @intCast(vaddr), endian),
|
||||
64 => mem.writeInt(u64, try code.addManyAsArray(8), vaddr, endian),
|
||||
else => unreachable,
|
||||
}
|
||||
@@ -859,6 +859,7 @@ fn genDeclRef(
|
||||
ptr_decl_index: InternPool.DeclIndex,
|
||||
) CodeGenError!GenResult {
|
||||
const zcu = lf.comp.module.?;
|
||||
const ip = &zcu.intern_pool;
|
||||
const ty = val.typeOf(zcu);
|
||||
log.debug("genDeclRef: val = {}", .{val.fmtValue(zcu)});
|
||||
|
||||
@@ -869,7 +870,7 @@ fn genDeclRef(
|
||||
const ptr_bits = target.ptrBitWidth();
|
||||
const ptr_bytes: u64 = @divExact(ptr_bits, 8);
|
||||
|
||||
const decl_index = switch (zcu.intern_pool.indexToKey(ptr_decl.val.toIntern())) {
|
||||
const decl_index = switch (ip.indexToKey(ptr_decl.val.toIntern())) {
|
||||
.func => |func| func.owner_decl,
|
||||
.extern_func => |extern_func| extern_func.decl,
|
||||
else => ptr_decl_index,
|
||||
@@ -909,12 +910,9 @@ fn genDeclRef(
|
||||
|
||||
if (lf.cast(link.File.Elf)) |elf_file| {
|
||||
if (is_extern) {
|
||||
const name = zcu.intern_pool.stringToSlice(decl.name);
|
||||
const name = decl.name.toSlice(ip);
|
||||
// TODO audit this
|
||||
const lib_name = if (decl.getOwnedVariable(zcu)) |ov|
|
||||
zcu.intern_pool.stringToSliceUnwrap(ov.lib_name)
|
||||
else
|
||||
null;
|
||||
const lib_name = if (decl.getOwnedVariable(zcu)) |ov| ov.lib_name.toSlice(ip) else null;
|
||||
const sym_index = try elf_file.getGlobalSymbol(name, lib_name);
|
||||
elf_file.symbol(elf_file.zigObjectPtr().?.symbol(sym_index)).flags.needs_got = true;
|
||||
return GenResult.mcv(.{ .load_symbol = sym_index });
|
||||
@@ -927,11 +925,8 @@ fn genDeclRef(
|
||||
return GenResult.mcv(.{ .load_symbol = sym.esym_index });
|
||||
} else if (lf.cast(link.File.MachO)) |macho_file| {
|
||||
if (is_extern) {
|
||||
const name = zcu.intern_pool.stringToSlice(decl.name);
|
||||
const lib_name = if (decl.getOwnedVariable(zcu)) |ov|
|
||||
zcu.intern_pool.stringToSliceUnwrap(ov.lib_name)
|
||||
else
|
||||
null;
|
||||
const name = decl.name.toSlice(ip);
|
||||
const lib_name = if (decl.getOwnedVariable(zcu)) |ov| ov.lib_name.toSlice(ip) else null;
|
||||
const sym_index = try macho_file.getGlobalSymbol(name, lib_name);
|
||||
macho_file.getSymbol(macho_file.getZigObject().?.symbols.items[sym_index]).flags.needs_got = true;
|
||||
return GenResult.mcv(.{ .load_symbol = sym_index });
|
||||
@@ -944,12 +939,9 @@ fn genDeclRef(
|
||||
return GenResult.mcv(.{ .load_symbol = sym.nlist_idx });
|
||||
} else if (lf.cast(link.File.Coff)) |coff_file| {
|
||||
if (is_extern) {
|
||||
const name = zcu.intern_pool.stringToSlice(decl.name);
|
||||
const name = decl.name.toSlice(ip);
|
||||
// TODO audit this
|
||||
const lib_name = if (decl.getOwnedVariable(zcu)) |ov|
|
||||
zcu.intern_pool.stringToSliceUnwrap(ov.lib_name)
|
||||
else
|
||||
null;
|
||||
const lib_name = if (decl.getOwnedVariable(zcu)) |ov| ov.lib_name.toSlice(ip) else null;
|
||||
const global_index = try coff_file.getGlobalSymbol(name, lib_name);
|
||||
try coff_file.need_got_table.put(gpa, global_index, {}); // needs GOT
|
||||
return GenResult.mcv(.{ .load_got = link.File.Coff.global_symbol_bit | global_index });
|
||||
@@ -1012,6 +1004,7 @@ pub fn genTypedValue(
|
||||
owner_decl_index: InternPool.DeclIndex,
|
||||
) CodeGenError!GenResult {
|
||||
const zcu = lf.comp.module.?;
|
||||
const ip = &zcu.intern_pool;
|
||||
const ty = val.typeOf(zcu);
|
||||
|
||||
log.debug("genTypedValue: val = {}", .{val.fmtValue(zcu)});
|
||||
@@ -1024,7 +1017,7 @@ pub fn genTypedValue(
|
||||
const target = namespace.file_scope.mod.resolved_target.result;
|
||||
const ptr_bits = target.ptrBitWidth();
|
||||
|
||||
if (!ty.isSlice(zcu)) switch (zcu.intern_pool.indexToKey(val.toIntern())) {
|
||||
if (!ty.isSlice(zcu)) switch (ip.indexToKey(val.toIntern())) {
|
||||
.ptr => |ptr| switch (ptr.addr) {
|
||||
.decl => |decl| return genDeclRef(lf, src_loc, val, decl),
|
||||
else => {},
|
||||
@@ -1041,7 +1034,7 @@ pub fn genTypedValue(
|
||||
return GenResult.mcv(.{ .immediate = 0 });
|
||||
},
|
||||
.none => {},
|
||||
else => switch (zcu.intern_pool.indexToKey(val.toIntern())) {
|
||||
else => switch (ip.indexToKey(val.toIntern())) {
|
||||
.int => {
|
||||
return GenResult.mcv(.{ .immediate = val.toUnsignedInt(zcu) });
|
||||
},
|
||||
@@ -1052,8 +1045,8 @@ pub fn genTypedValue(
|
||||
.Int => {
|
||||
const info = ty.intInfo(zcu);
|
||||
if (info.bits <= ptr_bits) {
|
||||
const unsigned = switch (info.signedness) {
|
||||
.signed => @as(u64, @bitCast(val.toSignedInt(zcu))),
|
||||
const unsigned: u64 = switch (info.signedness) {
|
||||
.signed => @bitCast(val.toSignedInt(zcu)),
|
||||
.unsigned => val.toUnsignedInt(zcu),
|
||||
};
|
||||
return GenResult.mcv(.{ .immediate = unsigned });
|
||||
@@ -1075,7 +1068,7 @@ pub fn genTypedValue(
|
||||
}
|
||||
},
|
||||
.Enum => {
|
||||
const enum_tag = zcu.intern_pool.indexToKey(val.toIntern()).enum_tag;
|
||||
const enum_tag = ip.indexToKey(val.toIntern()).enum_tag;
|
||||
return genTypedValue(
|
||||
lf,
|
||||
src_loc,
|
||||
@@ -1084,7 +1077,7 @@ pub fn genTypedValue(
|
||||
);
|
||||
},
|
||||
.ErrorSet => {
|
||||
const err_name = zcu.intern_pool.indexToKey(val.toIntern()).err.name;
|
||||
const err_name = ip.indexToKey(val.toIntern()).err.name;
|
||||
const error_index = zcu.global_error_set.getIndex(err_name).?;
|
||||
return GenResult.mcv(.{ .immediate = error_index });
|
||||
},
|
||||
@@ -1094,7 +1087,7 @@ pub fn genTypedValue(
|
||||
if (!payload_type.hasRuntimeBitsIgnoreComptime(zcu)) {
|
||||
// We use the error type directly as the type.
|
||||
const err_int_ty = try zcu.errorIntType();
|
||||
switch (zcu.intern_pool.indexToKey(val.toIntern()).error_union.val) {
|
||||
switch (ip.indexToKey(val.toIntern()).error_union.val) {
|
||||
.err_name => |err_name| return genTypedValue(
|
||||
lf,
|
||||
src_loc,
|
||||
|
||||
Reference in New Issue
Block a user