From 00b0beb682881da083b548423019483924736c1e Mon Sep 17 00:00:00 2001 From: binarycraft007 Date: Mon, 1 Sep 2025 17:01:54 +0800 Subject: [PATCH 1/2] lzma2: fix array list looping logic in appendLz --- lib/std/compress/lzma2.zig | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/lib/std/compress/lzma2.zig b/lib/std/compress/lzma2.zig index 46e06bedab..f5bd7206c5 100644 --- a/lib/std/compress/lzma2.zig +++ b/lib/std/compress/lzma2.zig @@ -83,11 +83,17 @@ pub const AccumBuffer = struct { return error.CorruptInput; } + // ensure we have enough capacity for all new bytes. + // This prevents the buffer's memory from being reallocated (and freed) + // while we are still reading from it. + try self.buf.ensureTotalCapacity(allocator, buf_len + len); + var offset = buf_len - dist; var i: usize = 0; while (i < len) : (i += 1) { const x = self.buf.items[offset]; - try self.buf.append(allocator, x); + // Since capacity is guaranteed, it's safe to use appendAssumeCapacity. + self.buf.appendAssumeCapacity(x); offset += 1; } self.len += len; From 90ac62cc751fa85bf572e281f65064bf2935ff9c Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Tue, 2 Sep 2025 12:00:43 -0700 Subject: [PATCH 2/2] std.compress.lzma2: optimize appendLz make the hot loop be a for loop without any failures or allocation. change a O(N) addition into O(1) --- lib/std/compress/lzma2.zig | 25 ++++++++++--------------- 1 file changed, 10 insertions(+), 15 deletions(-) diff --git a/lib/std/compress/lzma2.zig b/lib/std/compress/lzma2.zig index f5bd7206c5..41e251dace 100644 --- a/lib/std/compress/lzma2.zig +++ b/lib/std/compress/lzma2.zig @@ -79,23 +79,18 @@ pub const AccumBuffer = struct { _ = writer; const buf_len = self.buf.items.len; - if (dist > buf_len) { - return error.CorruptInput; - } + if (dist > buf_len) return error.CorruptInput; - // ensure we have enough capacity for all new bytes. - // This prevents the buffer's memory from being reallocated (and freed) - // while we are still reading from it. - try self.buf.ensureTotalCapacity(allocator, buf_len + len); + try self.buf.ensureUnusedCapacity(allocator, len); + const buffer = self.buf.allocatedSlice(); + const src = buffer[buf_len - dist ..][0..len]; + const dst = buffer[buf_len..][0..len]; - var offset = buf_len - dist; - var i: usize = 0; - while (i < len) : (i += 1) { - const x = self.buf.items[offset]; - // Since capacity is guaranteed, it's safe to use appendAssumeCapacity. - self.buf.appendAssumeCapacity(x); - offset += 1; - } + // This is not a @memmove; it intentionally repeats patterns caused by + // iterating one byte at a time. + for (dst, src) |*d, s| d.* = s; + + self.buf.items.len = buf_len + len; self.len += len; }