From eac621cd2ab72cc97bca51b046618e63df3ec976 Mon Sep 17 00:00:00 2001 From: anshalshukla Date: Mon, 19 Jan 2026 21:24:02 +0530 Subject: [PATCH] fix: chunking --- snappy.zig | 41 +++++++++++++++++++++++++++++++++-------- 1 file changed, 33 insertions(+), 8 deletions(-) diff --git a/snappy.zig b/snappy.zig index f01b0c8..06c994a 100644 --- a/snappy.zig +++ b/snappy.zig @@ -434,14 +434,11 @@ pub fn encode(allocator: Allocator, src: []const u8) ![]u8 { var d = putUvarint(dst, @as(u64, @intCast(mutSrc.len))); while (mutSrc.len > 0) { - var p = try allocator.alloc(u8, mutSrc.len); - std.mem.copyForwards(u8, p, mutSrc); - var empty = [_]u8{}; - mutSrc = empty[0..]; - if (p.len > maxBlockSize) { - mutSrc = p[maxBlockSize..]; - p = p[0..maxBlockSize]; - } + const chunk_len = @min(mutSrc.len, maxBlockSize); + const p = try allocator.alloc(u8, chunk_len); + std.mem.copyForwards(u8, p, mutSrc[0..chunk_len]); + mutSrc = mutSrc[chunk_len..]; + if (p.len < minNonLiteralBlockSize) { d += emitLiteral(dst[d..], p); } else { @@ -547,3 +544,31 @@ test "emit literal length > 65535" { try testing.expectEqual(@as(u8, @intCast(n >> 16)), dst[3]); try testing.expectEqualSlices(u8, lit[0..], dst[4 .. 4 + lit.len]); } + +test "encode larger than maxBlockSize" { + // This test verifies that encoding data larger than maxBlockSize (65536 bytes) + // correctly handles memory allocation. Previously, the encode function would + // allocate the full remaining size, then shrink the slice before freeing, + // causing an allocation size mismatch error. + const allocator = testing.allocator; + + // Create input larger than maxBlockSize (65536) to trigger chunking + const input_size = 100_000; + const input = try allocator.alloc(u8, input_size); + defer allocator.free(input); + + // Fill with pattern + for (input, 0..) |*b, i| { + b.* = @as(u8, @truncate(i)); + } + + // Encode - this would fail with allocation mismatch on buggy implementation + const encoded = try encode(allocator, input); + defer allocator.free(encoded); + + // Decode and verify roundtrip + const decoded = try decode(allocator, encoded); + defer allocator.free(decoded); + + try testing.expectEqualSlices(u8, input, decoded); +}