diff --git a/lib/compiler/objcopy.zig b/lib/compiler/objcopy.zig index 7ca09e6b48ed69685ecc73c5a0787b6fae7da885..b2b0f270bde26aa0f9e4016e5fd8a63f9d5af4bd 100644 --- a/lib/compiler/objcopy.zig +++ b/lib/compiler/objcopy.zig @@ -409,7 +409,7 @@ const BinaryElfOutput = struct { const shstrtab_shdr = (try section_headers.next()).?; try in.seekTo(shstrtab_shdr.sh_offset); - break :blk try in.interface.readAlloc(allocator, shstrtab_shdr.sh_size); + break :blk try in.interface.readAllocAll(allocator, shstrtab_shdr.sh_size); }; errdefer if (self.shstrtab) |shstrtab| allocator.free(shstrtab); diff --git a/lib/compiler/objdump.zig b/lib/compiler/objdump.zig index 94e3bec51b952c64c0b3065a34d54922e9b17ea4..b1752aee70b060f0b9a779964276f16486590cb1 100644 --- a/lib/compiler/objdump.zig +++ b/lib/compiler/objdump.zig @@ -417,7 +417,7 @@ const coff = struct { \\ ); - const offsets = try r.readAlloc(gpa, num_symbols * 4); + const offsets = try r.readAllocAll(gpa, num_symbols * 4); defer gpa.free(offsets); for (0..num_symbols) |symbol_i| { @@ -549,7 +549,7 @@ const coff = struct { .longnames => { // This member is optional if (std.mem.eql(u8, header.name, "//")) { - opt_longnames = try r.readAlloc(gpa, header.size); + opt_longnames = try r.readAllocAll(gpa, header.size); if (dump_header) try w.print("{t: >16} type\n", .{expected_kind}); @@ -819,7 +819,7 @@ const coff = struct { const string_table_len = r.peekInt(u32, .little) catch |err| return d.failParse("unable to read string table length: {t}", .{err}); - const table = r.readAlloc(gpa, string_table_len) catch |err| + const table = r.readAllocAll(gpa, string_table_len) catch |err| return d.failParse("unable to read string table: {t}", .{err}); try fr.seekTo(pos); @@ -1268,7 +1268,7 @@ const coff = struct { const dir = image_info.?.data_dirs[@backingInt(DIRECTORY_ENTRY.EXPORT)]; const dir_end_rva = dir.virtual_address + dir.size; const dir_loc = fr.logicalPos(); - const dir_slice = try r.readAlloc(gpa, dir.size); + const dir_slice = try r.readAllocAll(gpa, dir.size); defer gpa.free(dir_slice); const dll_name = std.mem.sliceTo(dir_slice[name_loc - dir_loc ..], 0); diff --git a/lib/std/Io/Reader.zig b/lib/std/Io/Reader.zig index 947f01694bcf6a1dea849bb7bbadef92c3f57096..c8797f26c68bdc41778f6360d75e591c78e10396 100644 --- a/lib/std/Io/Reader.zig +++ b/lib/std/Io/Reader.zig @@ -744,14 +744,27 @@ pub inline fn readSliceEndianAlloc( return dest; } +/// Deprecated; use readAllocAll. to be removed after 0.17. +pub const readAlloc = readAllocAll; + /// Shortcut for calling `readSliceAll` with a buffer provided by `allocator`. -pub fn readAlloc(r: *Reader, allocator: Allocator, len: usize) ReadAllocError![]u8 { +pub fn readAllocAll(r: *Reader, allocator: Allocator, len: usize) ReadAllocError![]u8 { const dest = try allocator.alloc(u8, len); errdefer allocator.free(dest); try readSliceAll(r, dest); return dest; } +/// Shortcut for calling `readSliceShort` with a buffer provided by `allocator`, +/// shrinking allocation if stream reached the end. +pub fn readAllocShort(r: *Reader, allocator: Allocator, len: usize) ReadAllocError![]u8 { + const dest = try allocator.alloc(u8, len); + errdefer allocator.free(dest); + const n = try readSliceShort(r, dest); + if (n == dest.len) return dest; + return try allocator.realloc(dest, n); +} + pub const DelimiterError = error{ /// See the `Reader` implementation for detailed diagnostics. ReadFailed, @@ -1746,6 +1759,47 @@ test "readSliceShort with indirect reader" { try testing.expectEqual(0, try ri.interface.readSliceShort(&buf)); } +test readAllocAll { + const allocator = testing.allocator; + var r: Reader = .fixed("HelloFren"); + + const s1 = try r.readAllocAll(allocator, 5); + defer allocator.free(s1); + try testing.expectEqualStrings("Hello", s1); + + const s2 = try r.readAllocAll(allocator, 4); + defer allocator.free(s2); + try testing.expectEqualStrings("Fren", s2); +} + +test "readAllocAll with buffer bigger than content" { + const allocator = testing.allocator; + var r: Reader = .fixed("HelloFren"); + + const s1 = try r.readAllocAll(allocator, 5); + defer allocator.free(s1); + try testing.expectEqualStrings("Hello", s1); + + const res = r.readAllocAll(allocator, 10); + try testing.expectError(Error.EndOfStream, res); +} + +test readAllocShort { + var r: Reader = .fixed("HelloFren"); + + const s1 = try r.readAllocShort(testing.allocator, 5); + defer testing.allocator.free(s1); + try testing.expectEqualStrings("Hello", s1); + + const s2 = try r.readAllocShort(testing.allocator, 10); + defer testing.allocator.free(s2); + try testing.expectEqualStrings("Fren", s2); + + const s3 = try r.readAllocShort(testing.allocator, 10); + defer testing.allocator.free(s3); + try testing.expectEqual(0, s3.len); +} + test readVec { var r: Reader = .fixed(std.ascii.letters); var flat_buffer: [52]u8 = undefined; diff --git a/lib/std/debug/Pdb.zig b/lib/std/debug/Pdb.zig index 2fa0478e353cd1c86694a247baae7b689ce47bdf..0ab115b188362a3ff4944ac20379872f31642067 100644 --- a/lib/std/debug/Pdb.zig +++ b/lib/std/debug/Pdb.zig @@ -171,7 +171,7 @@ pub fn parseIpiStream(self: *Pdb) !void { const header = try stream.interface.peekStruct(pdb.IpiStreamHeader, .little); if (header.version != .v80) // only value observed by LLVM team return error.UnknownPDBVersion; - self.ipi = try stream.interface.readAlloc(gpa, @sizeOf(pdb.IpiStreamHeader) + header.type_record_bytes); + self.ipi = try stream.interface.readAllocAll(gpa, @sizeOf(pdb.IpiStreamHeader) + header.type_record_bytes); } pub fn parseInfoStream(self: *Pdb) !void { @@ -196,7 +196,7 @@ pub fn parseInfoStream(self: *Pdb) !void { // Find the string table. const string_table_index = str_tab_index: { const name_bytes_len = try reader.takeInt(u32, .little); - const name_bytes = try reader.readAlloc(gpa, name_bytes_len); + const name_bytes = try reader.readAllocAll(gpa, name_bytes_len); defer gpa.free(name_bytes); const HashTableHeader = extern struct { @@ -865,9 +865,9 @@ pub fn getModule(self: *Pdb, index: usize) !?*Module { const gpa = self.allocator; - mod.symbols = try reader.readAlloc(gpa, mod.mod_info.sym_byte_size - 4); + mod.symbols = try reader.readAllocAll(gpa, mod.mod_info.sym_byte_size - 4); errdefer gpa.free(mod.symbols); - mod.subsect_info = try reader.readAlloc(gpa, mod.mod_info.c13_byte_size); + mod.subsect_info = try reader.readAllocAll(gpa, mod.mod_info.c13_byte_size); errdefer gpa.free(mod.subsect_info); mod.inlinee_source_lines = b: { var inlinee_source_lines: std.ArrayList(*align(1) const pdb.InlineeSourceLine) = .empty; diff --git a/src/link/Coff.zig b/src/link/Coff.zig index eb8f89717f9f2dd2dfa6dec437ba0cd0485b5b39..d8934d79d89cff328b413aaec7ef173be957adff 100644 --- a/src/link/Coff.zig +++ b/src/link/Coff.zig @@ -5290,7 +5290,7 @@ fn loadArchive(coff: *Coff, path: std.Build.Cache.Path, fr: *Io.File.Reader) Loa .longnames => { // This member is optional if (std.mem.eql(u8, res.name, "//")) - opt_longnames = try r.readAlloc(gpa, @intCast(res.size)); + opt_longnames = try r.readAllocAll(gpa, @intCast(res.size)); opt_expected_kind = null; break;