diff options
| author | Jacob Young <jacobly0@users.noreply.github.com> | 2024-04-08 12:44:42 -0400 |
|---|---|---|
| committer | Jacob Young <jacobly0@users.noreply.github.com> | 2024-04-08 13:24:08 -0400 |
| commit | 7611d90ba011fb030523e669e85acfb6faae5d19 (patch) | |
| tree | f1b48f3ac73681c402dce10b5857ecc0f84dd7a4 /src/codegen.zig | |
| parent | 4cd92567e7392b0fe390562d7ea52f68357bb45a (diff) | |
| download | zig-7611d90ba011fb030523e669e85acfb6faae5d19.tar.gz zig-7611d90ba011fb030523e669e85acfb6faae5d19.zip | |
InternPool: remove slice from byte aggregate keys
This deletes a ton of lookups and avoids many UAF bugs.
Closes #19485
Diffstat (limited to 'src/codegen.zig')
| -rw-r--r-- | src/codegen.zig | 107 |
1 files changed, 50 insertions, 57 deletions
diff --git a/src/codegen.zig b/src/codegen.zig index 76be8be974..b45777564a 100644 --- a/src/codegen.zig +++ b/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, |
