-
-
Notifications
You must be signed in to change notification settings - Fork 3k
Description
Zig Version
0.15.0-dev.1267+da408bd6f
Steps to Reproduce and Observed Behavior
Using a zstd.Decompress
with an 80 mb buffer:
const args = try std.process.argsAlloc(allocator);
defer std.process.argsFree(allocator, args);
if (args.len < 2) {
std.debug.print("Usage: {s} <file>\n", .{args[0]});
return;
}
const path = args[1];
const file = if (std.fs.path.isAbsolute(path))
try std.fs.openFileAbsolute(path, .{})
else
try std.fs.cwd().openFile(path, .{});
const stat = try file.stat();
std.debug.print("file is {B}\n", .{stat.size});
var file_buffer: [4096]u8 = undefined;
var file_reader = file.reader(&file_buffer);
const zstd_buffer = try allocator.alloc(u8, 10 * (zstd.default_window_len + zstd.block_size_max));
defer allocator.free(zstd_buffer);
var zstd_reader: std.compress.zstd.Decompress = .init(&file_reader.interface, zstd_buffer, .{});
these don't work, and i think should:
1) Reading byte-by-byte
for (0..1_000_000) |i| {
const b = try zstd_reader.reader.takeByte();
if ((i % 1000) == 0) {
std.debug.print("{d}\n", .{b});
}
}
has this error:
error: ReadFailed
zig/build/stage3/lib/zig/std/math.zig:578:21: 0x104d2f63f in sub__anon_11112 (repro)
if (ov[1] != 0) return error.Overflow;
^
zig/build/stage3/lib/zig/std/compress/zstd/Decompress.zig:671:21: 0x104d975d7 in decodeSequence (repro)
return error.MalformedSequence;
^
zig/build/stage3/lib/zig/std/compress/zstd/Decompress.zig:219:42: 0x104d98d5f in readInFrame (repro)
bytes_written += try decode.decodeSequence(w.buffer, write_pos + bytes_written, &bit_stream);
^
zig/build/stage3/lib/zig/std/compress/zstd/Decompress.zig:138:21: 0x104d921fb in stream (repro)
return error.ReadFailed;
^
zig/build/stage3/lib/zig/std/Io/Reader.zig:1063:25: 0x104daa55f in fillUnbuffered (repro)
else => |e| return e,
^
zig/build/stage3/lib/zig/std/Io/Reader.zig:1046:5: 0x104d9d267 in fill (repro)
return fillUnbuffered(r, n);
^
zig/build/stage3/lib/zig/std/Io/Reader.zig:1111:5: 0x104d928bf in peekByte (repro)
try fill(r, 1);
^
zig/build/stage3/lib/zig/std/Io/Reader.zig:1119:20: 0x104d8e95f in takeByte (repro)
const result = try peekByte(r);
^
repro.zig:42:19: 0x104d8e183 in main (repro)
const b = try zstd_reader.reader.takeByte();
2) Reading using slices
var buffer: [1024]u8 = undefined;
for (0..1024) |i| {
std.debug.print("{d}\n", .{i});
try zstd_reader.reader.readSliceAll(&buffer);
}
fails with
error: ReadFailed
zig/std/math.zig:578:21: 0x10091b63f in sub__anon_11112 (repro)
if (ov[1] != 0) return error.Overflow;
^
zig/std/compress/zstd/Decompress.zig:671:21: 0x100983a87 in decodeSequence (repro)
return error.MalformedSequence;
^
zig/std/compress/zstd/Decompress.zig:219:42: 0x10098520f in readInFrame (repro)
bytes_written += try decode.decodeSequence(w.buffer, write_pos + bytes_written, &bit_stream);
^
zig/std/compress/zstd/Decompress.zig:138:21: 0x10097e1cf in stream (repro)
return error.ReadFailed;
^
zig/std/Io/Reader.zig:408:21: 0x1009898db in readVecInner (repro)
else => |e| return e,
^
zig/std/Io/Reader.zig:662:33: 0x10097edff in readSliceShort (repro)
error.ReadFailed => return error.ReadFailed,
^
zig/std/Io/Reader.zig:630:15: 0x10097aa37 in readSliceAll (repro)
const n = try readSliceShort(r, buffer);
^
repro.zig:45:9: 0x10097a1a7 in main (repro)
try zstd_reader.reader.readSliceAll(&buffer);
^
3) streamExact
1k to stdout using a 80mb stdout buffer
const stdout_buffer = try allocator.alloc(u8, 10 * (zstd.default_window_len + zstd.block_size_max));
defer allocator.free(stdout_buffer);
var stdout = std.fs.File.stdout().writer(stdout_buffer);
try zstd_reader.reader.streamExact(&stdout.interface, 1024);
fails with
error: ReadFailed
zig/std/compress/zstd/Decompress.zig:182:43: 0x10252414b in readInFrame (repro)
if (@intFromEnum(limit) < block_size) return error.OutputBufferUndersize;
^
zig/std/compress/zstd/Decompress.zig:128:21: 0x10251e0bf in stream (repro)
return error.ReadFailed;
^
zig/std/Io/Reader.zig:159:15: 0x10249ac17 in stream (repro)
const n = try r.vtable.stream(r, w, limit);
^
zig/std/Io/Reader.zig:196:41: 0x10251ad5f in streamExact (repro)
while (remaining != 0) remaining -= try r.stream(w, .limited(remaining));
^
repro.zig:57:5: 0x10251a1fb in main (repro)
try zstd_reader.reader.streamExact(&stdout.interface, 1024);
^
4) using allocRemaining
to read one block size:
const buf = try zstd_reader.reader.allocRemaining(allocator, .limited(zstd.block_size_max));
std.debug.print("took {d}\n", .{buf.len});
fails with
error: ReadFailed
zig/std/compress/zstd/Decompress.zig:817:13: 0x1023269d3 in init (repro)
return error.WindowOversize
^
zig/std/compress/zstd/Decompress.zig:161:26: 0x102326143 in initFrame (repro)
.frame = try Frame.init(header, window_size_max, d.verify_checksum),
^
zig/std/compress/zstd/Decompress.zig:121:17: 0x102321f13 in stream (repro)
return error.ReadFailed;
^
zig/std/Io/Reader.zig:327:37: 0x102322ef7 in appendRemaining__anon_19657 (repro)
error.ReadFailed => return error.ReadFailed,
^
zig/std/Io/Reader.zig:275:5: 0x10231e967 in allocRemaining (repro)
try appendRemaining(r, gpa, null, &buffer, limit);
^
repro.zig:41:17: 0x10231e0ef in main (repro)
const buf = try zstd_reader.reader.allocRemaining(allocator, .limited(zstd.block_size_max));
^
5) using take()
to get larger than block_size_max
const buf = try zstd_reader.reader.take(2 * zstd.block_size_max);
std.debug.print("took {d}\n", .{buf.len});
fails with the same error as above:
error: ReadFailed
zig/std/math.zig:578:21: 0x100f2f63f in sub__anon_11112 (repro)
if (ov[1] != 0) return error.Overflow;
^
zig/std/compress/zstd/Decompress.zig:671:21: 0x100f9754f in decodeSequence (repro)
return error.MalformedSequence;
^
zig/std/compress/zstd/Decompress.zig:219:42: 0x100f98cd7 in readInFrame (repro)
bytes_written += try decode.decodeSequence(w.buffer, write_pos + bytes_written, &bit_stream);
^
zig/std/compress/zstd/Decompress.zig:138:21: 0x100f921a3 in stream (repro)
return error.ReadFailed;
^
zig/std/Io/Reader.zig:1063:25: 0x100faa3df in fillUnbuffered (repro)
else => |e| return e,
^
zig/std/Io/Reader.zig:1046:5: 0x100f9d2ef in fill (repro)
return fillUnbuffered(r, n);
^
zig/std/Io/Reader.zig:478:5: 0x100f92723 in peek (repro)
try r.fill(n);
^
zig/std/Io/Reader.zig:527:20: 0x100f8e907 in take (repro)
const result = try r.peek(n);
^
repro.zig:44:17: 0x100f8e0d7 in main (repro)
const buf = try zstd_reader.reader.take(2 * zstd.block_size_max);
^
There are other test cases that we could run that similarly fail. I guess, after looking at it, I would suggest that all of these are code that a user would think should work, and that the main issue appears to be mixing the concept of the zstd.Decompress
buffer that maybe should be an interim decompressed bytes location that can be take()
or readSliceAll()
from, but then when an output writer is used, it might try and use the output writer for that decompressed data which also means that you can't have smaller (or larger) than block size writes...
Expected Behavior
I think these cases should work.