Skip to content

Commit bbd13ab

Browse files
squeek502alexrp
authored andcommitted
rescanMac: Avoid overallocating/overreading by millions of bytes
readAtLeast is greedy and will read the entire length of the buffer if it can. However, reading past the end of the cert in this case is useless, so reading the full length of the buffer just puts an increasingly large (due to the growth algorithm of ArrayList) collection of wasted bytes after each cert in cb.bytes. In practical terms, this ends up saving potentially millions of bytes of wasted reads/allocations. In my testing, after reading the keychain files on my machine, cb.bytes ends up with these capacities: - Before: cb.bytes.capacity = 32720747 - After: cb.bytes.capacity = 251937 That's a decrease of 99.2% Additionally, swaps to readNoEof since it should be an error to hit EOF without reading the full cert size.
1 parent 253e641 commit bbd13ab

File tree

1 file changed

+2
-4
lines changed

1 file changed

+2
-4
lines changed

lib/std/crypto/Certificate/Bundle/macos.zig

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -71,11 +71,9 @@ pub fn rescanMac(cb: *Bundle, gpa: Allocator) RescanMacError!void {
7171

7272
if (cert_header.cert_size == 0) continue;
7373

74-
try cb.bytes.ensureUnusedCapacity(gpa, cert_header.cert_size);
75-
7674
const cert_start = @as(u32, @intCast(cb.bytes.items.len));
77-
const dest_buf = cb.bytes.allocatedSlice()[cert_start..];
78-
cb.bytes.items.len += try reader.readAtLeast(dest_buf, cert_header.cert_size);
75+
const dest_buf = try cb.bytes.addManyAsSlice(gpa, cert_header.cert_size);
76+
try reader.readNoEof(dest_buf);
7977

8078
try cb.parseCert(gpa, cert_start, now_sec);
8179
}

0 commit comments

Comments
 (0)