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/Module.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/Module.zig')
| -rw-r--r-- | src/Module.zig | 113 |
1 files changed, 63 insertions, 50 deletions
diff --git a/src/Module.zig b/src/Module.zig index 0399a2f85b..c4d7f43fe4 100644 --- a/src/Module.zig +++ b/src/Module.zig @@ -763,11 +763,11 @@ pub const Namespace = struct { ) !InternPool.NullTerminatedString { const ip = &zcu.intern_pool; const count = count: { - var count: usize = ip.stringToSlice(name).len + 1; + var count: usize = name.length(ip) + 1; var cur_ns = &ns; while (true) { const decl = zcu.declPtr(cur_ns.decl_index); - count += ip.stringToSlice(decl.name).len + 1; + count += decl.name.length(ip) + 1; cur_ns = zcu.namespacePtr(cur_ns.parent.unwrap() orelse { count += ns.file_scope.sub_file_path.len; break :count count; @@ -793,7 +793,7 @@ pub const Namespace = struct { }; } - return ip.getOrPutTrailingString(gpa, ip.string_bytes.items.len - start); + return ip.getOrPutTrailingString(gpa, ip.string_bytes.items.len - start, .no_embedded_nulls); } pub fn getType(ns: Namespace, zcu: *Zcu) Type { @@ -980,17 +980,13 @@ pub const File = struct { const ip = &mod.intern_pool; const start = ip.string_bytes.items.len; try file.renderFullyQualifiedName(ip.string_bytes.writer(mod.gpa)); - return ip.getOrPutTrailingString(mod.gpa, ip.string_bytes.items.len - start); + return ip.getOrPutTrailingString(mod.gpa, ip.string_bytes.items.len - start, .no_embedded_nulls); } pub fn fullPath(file: File, ally: Allocator) ![]u8 { return file.mod.root.joinString(ally, file.sub_file_path); } - pub fn fullPathZ(file: File, ally: Allocator) ![:0]u8 { - return file.mod.root.joinStringZ(ally, file.sub_file_path); - } - pub fn dumpSrc(file: *File, src: LazySrcLoc) void { const loc = std.zig.findLineColumn(file.source.bytes, src); std.debug.print("{s}:{d}:{d}\n", .{ file.sub_file_path, loc.line + 1, loc.column + 1 }); @@ -2534,6 +2530,7 @@ fn updateZirRefs(zcu: *Module, file: *File, old_zir: Zir) !void { const name_ip = try zcu.intern_pool.getOrPutString( zcu.gpa, old_zir.nullTerminatedString(name_zir), + .no_embedded_nulls, ); try old_names.put(zcu.gpa, name_ip, {}); } @@ -2551,6 +2548,7 @@ fn updateZirRefs(zcu: *Module, file: *File, old_zir: Zir) !void { const name_ip = try zcu.intern_pool.getOrPutString( zcu.gpa, old_zir.nullTerminatedString(name_zir), + .no_embedded_nulls, ); if (!old_names.swapRemove(name_ip)) continue; // Name added @@ -3555,37 +3553,46 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !SemaDeclResult { const gpa = mod.gpa; const zir = decl.getFileScope(mod).zir; - const builtin_type_target_index: InternPool.Index = blk: { + const builtin_type_target_index: InternPool.Index = ip_index: { const std_mod = mod.std_mod; - if (decl.getFileScope(mod).mod != std_mod) break :blk .none; + if (decl.getFileScope(mod).mod != std_mod) break :ip_index .none; // We're in the std module. const std_file = (try mod.importPkg(std_mod)).file; const std_decl = mod.declPtr(std_file.root_decl.unwrap().?); const std_namespace = std_decl.getInnerNamespace(mod).?; - const builtin_str = try ip.getOrPutString(gpa, "builtin"); - const builtin_decl = mod.declPtr(std_namespace.decls.getKeyAdapted(builtin_str, DeclAdapter{ .zcu = mod }) orelse break :blk .none); - const builtin_namespace = builtin_decl.getInnerNamespaceIndex(mod).unwrap() orelse break :blk .none; - if (decl.src_namespace != builtin_namespace) break :blk .none; + const builtin_str = try ip.getOrPutString(gpa, "builtin", .no_embedded_nulls); + const builtin_decl = mod.declPtr(std_namespace.decls.getKeyAdapted(builtin_str, DeclAdapter{ .zcu = mod }) orelse break :ip_index .none); + const builtin_namespace = builtin_decl.getInnerNamespaceIndex(mod).unwrap() orelse break :ip_index .none; + if (decl.src_namespace != builtin_namespace) break :ip_index .none; // We're in builtin.zig. This could be a builtin we need to add to a specific InternPool index. - for ([_]struct { []const u8, InternPool.Index }{ - .{ "AtomicOrder", .atomic_order_type }, - .{ "AtomicRmwOp", .atomic_rmw_op_type }, - .{ "CallingConvention", .calling_convention_type }, - .{ "AddressSpace", .address_space_type }, - .{ "FloatMode", .float_mode_type }, - .{ "ReduceOp", .reduce_op_type }, - .{ "CallModifier", .call_modifier_type }, - .{ "PrefetchOptions", .prefetch_options_type }, - .{ "ExportOptions", .export_options_type }, - .{ "ExternOptions", .extern_options_type }, - .{ "Type", .type_info_type }, - }) |pair| { - const decl_name = ip.stringToSlice(decl.name); - if (std.mem.eql(u8, decl_name, pair[0])) { - break :blk pair[1]; - } + for ([_][]const u8{ + "AtomicOrder", + "AtomicRmwOp", + "CallingConvention", + "AddressSpace", + "FloatMode", + "ReduceOp", + "CallModifier", + "PrefetchOptions", + "ExportOptions", + "ExternOptions", + "Type", + }, [_]InternPool.Index{ + .atomic_order_type, + .atomic_rmw_op_type, + .calling_convention_type, + .address_space_type, + .float_mode_type, + .reduce_op_type, + .call_modifier_type, + .prefetch_options_type, + .export_options_type, + .extern_options_type, + .type_info_type, + }) |type_name, type_ip| { + if (decl.name.eqlSlice(type_name, ip)) break :ip_index type_ip; } - break :blk .none; + break :ip_index .none; }; mod.intern_pool.removeDependenciesForDepender(gpa, InternPool.Depender.wrap(.{ .decl = decl_index })); @@ -3725,8 +3732,7 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !SemaDeclResult { } else if (bytes.len == 0) { return sema.fail(&block_scope, section_src, "linksection cannot be empty", .{}); } - const section = try ip.getOrPutString(gpa, bytes); - break :blk section.toOptional(); + break :blk try ip.getOrPutStringOpt(gpa, bytes, .no_embedded_nulls); }; decl.@"addrspace" = blk: { const addrspace_ctx: Sema.AddressSpaceContext = switch (ip.indexToKey(decl_val.toIntern())) { @@ -4101,7 +4107,10 @@ fn newEmbedFile( .sentinel = .zero_u8, .child = .u8_type, } }); - const array_val = try ip.getTrailingAggregate(gpa, array_ty, bytes.len); + const array_val = try ip.get(gpa, .{ .aggregate = .{ + .ty = array_ty, + .storage = .{ .bytes = try ip.getOrPutTrailingString(gpa, bytes.len, .maybe_embedded_nulls) }, + } }); const ptr_ty = (try mod.ptrType(.{ .child = array_ty, @@ -4111,7 +4120,6 @@ fn newEmbedFile( .address_space = .generic, }, })).toIntern(); - const ptr_val = try ip.get(gpa, .{ .ptr = .{ .ty = ptr_ty, .addr = .{ .anon_decl = .{ @@ -4122,7 +4130,7 @@ fn newEmbedFile( result.* = new_file; new_file.* = .{ - .sub_file_path = try ip.getOrPutString(gpa, sub_file_path), + .sub_file_path = try ip.getOrPutString(gpa, sub_file_path, .no_embedded_nulls), .owner = pkg, .stat = stat, .val = ptr_val, @@ -4214,11 +4222,11 @@ const ScanDeclIter = struct { const zcu = iter.zcu; const gpa = zcu.gpa; const ip = &zcu.intern_pool; - var name = try ip.getOrPutStringFmt(gpa, fmt, args); + var name = try ip.getOrPutStringFmt(gpa, fmt, args, .no_embedded_nulls); var gop = try iter.seen_decls.getOrPut(gpa, name); var next_suffix: u32 = 0; while (gop.found_existing) { - name = try ip.getOrPutStringFmt(gpa, fmt ++ "_{d}", args ++ .{next_suffix}); + name = try ip.getOrPutStringFmt(gpa, "{}_{d}", .{ name.fmt(ip), next_suffix }, .no_embedded_nulls); gop = try iter.seen_decls.getOrPut(gpa, name); next_suffix += 1; } @@ -4300,7 +4308,11 @@ fn scanDecl(iter: *ScanDeclIter, decl_inst: Zir.Inst.Index) Allocator.Error!void }; } else info: { if (iter.pass != .named) return; - const name = try ip.getOrPutString(gpa, zir.nullTerminatedString(declaration.name.toString(zir).?)); + const name = try ip.getOrPutString( + gpa, + zir.nullTerminatedString(declaration.name.toString(zir).?), + .no_embedded_nulls, + ); try iter.seen_decls.putNoClobber(gpa, name, {}); break :info .{ name, @@ -4362,9 +4374,10 @@ fn scanDecl(iter: *ScanDeclIter, decl_inst: Zir.Inst.Index) Allocator.Error!void if (!comp.config.is_test) break :a false; if (decl_mod != zcu.main_mod) break :a false; if (is_named_test and comp.test_filters.len > 0) { - const decl_fqn = ip.stringToSlice(try namespace.fullyQualifiedName(zcu, decl_name)); + const decl_fqn = try namespace.fullyQualifiedName(zcu, decl_name); + const decl_fqn_slice = decl_fqn.toSlice(ip); for (comp.test_filters) |test_filter| { - if (mem.indexOf(u8, decl_fqn, test_filter)) |_| break; + if (mem.indexOf(u8, decl_fqn_slice, test_filter)) |_| break; } else break :a false; } zcu.test_functions.putAssumeCapacity(decl_index, {}); // may clobber on incremental update @@ -4377,8 +4390,8 @@ fn scanDecl(iter: *ScanDeclIter, decl_inst: Zir.Inst.Index) Allocator.Error!void // `is_export` is unchanged. In this case, the incremental update mechanism will handle // re-analysis for us if necessary. if (prev_exported != declaration.flags.is_export or decl.analysis == .unreferenced) { - log.debug("scanDecl queue analyze_decl file='{s}' decl_name='{s}' decl_index={d}", .{ - namespace.file_scope.sub_file_path, ip.stringToSlice(decl_name), decl_index, + log.debug("scanDecl queue analyze_decl file='{s}' decl_name='{}' decl_index={d}", .{ + namespace.file_scope.sub_file_path, decl_name.fmt(ip), decl_index, }); comp.work_queue.writeItemAssumeCapacity(.{ .analyze_decl = decl_index }); } @@ -5300,7 +5313,7 @@ pub fn populateTestFunctions( const builtin_file = (mod.importPkg(builtin_mod) catch unreachable).file; const root_decl = mod.declPtr(builtin_file.root_decl.unwrap().?); const builtin_namespace = mod.namespacePtr(root_decl.src_namespace); - const test_functions_str = try ip.getOrPutString(gpa, "test_functions"); + const test_functions_str = try ip.getOrPutString(gpa, "test_functions", .no_embedded_nulls); const decl_index = builtin_namespace.decls.getKeyAdapted( test_functions_str, DeclAdapter{ .zcu = mod }, @@ -5327,16 +5340,16 @@ pub fn populateTestFunctions( for (test_fn_vals, mod.test_functions.keys()) |*test_fn_val, test_decl_index| { const test_decl = mod.declPtr(test_decl_index); - const test_decl_name = try gpa.dupe(u8, ip.stringToSlice(try test_decl.fullyQualifiedName(mod))); - defer gpa.free(test_decl_name); + const test_decl_name = try test_decl.fullyQualifiedName(mod); + const test_decl_name_len = test_decl_name.length(ip); const test_name_anon_decl: InternPool.Key.Ptr.Addr.AnonDecl = n: { const test_name_ty = try mod.arrayType(.{ - .len = test_decl_name.len, + .len = test_decl_name_len, .child = .u8_type, }); const test_name_val = try mod.intern(.{ .aggregate = .{ .ty = test_name_ty.toIntern(), - .storage = .{ .bytes = test_decl_name }, + .storage = .{ .bytes = test_decl_name.toString() }, } }); break :n .{ .orig_ty = (try mod.singleConstPtrType(test_name_ty)).toIntern(), @@ -5354,7 +5367,7 @@ pub fn populateTestFunctions( } }), .len = try mod.intern(.{ .int = .{ .ty = .usize_type, - .storage = .{ .u64 = test_decl_name.len }, + .storage = .{ .u64 = test_decl_name_len }, } }), } }), // func |
