Open squeek502 opened 2 weeks ago
Addendum: this is seemingly not an isolated incident. Adding this:
comptime {
if (ReadError || error{EndOfStream} == ReadError) {
@compileError("ReadError cannot contain EndOfStream");
}
}
to GenericReader
, it gets triggered from:
lib\std\compress\flate\inflate.zig:344:41: note: called from here
pub const Reader = std.io.Reader(*Self, Error, read);
~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~
lib\std\compress\flate\inflate.zig:344:41: note: called from here
pub const Reader = std.io.Reader(*Self, Error, read);
~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~
lib\std\http\Client.zig:940:41: note: called from here
const TransferReader = std.io.Reader(*Request, TransferReadError, transferRead);
~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
lib\std\compress\lzma.zig:33:41: note: called from here
pub const Reader = std.io.Reader(*Self, Error, read);
~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~
lib\std\compress\xz.zig:37:41: note: called from here
pub const Reader = std.io.Reader(*Self, Error, read);
~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~
so presumably this same type of bug could exist with all of those GenericReader
implementations as well. However, it may not necessarily be a bug in every case (it only leads to problems if it is accidentally being used to signal "no more data to read"); I was just curious how many other GenericReader
errors contained EndOfStream
.
A simple but potentially naive fix could look like this (relevant code):
- const record_count = try std.leb.readULEB128(u64, counting_reader);
+ const record_count = std.leb.readULEB128(u64, counting_reader) catch |err| switch (err) {
+ error.EndOfStream => return 0,
+ else => |e| return e,
+ };
This fixes the tests in the OP, but there might be a better way to determine when this EndOfStream
should be treated as unrecoverable or as "no more data to read."
Zig Version
0.14.0-dev.117+5f5895626
Steps to Reproduce and Observed Behavior
This test added to
lib/std/compress/xz/test.zig
:will error with
This is because the
read
implementation can returnEndOfStream
from many different places within itsread
implementation, even though it likely should be returning0
to signal there's nothing left to read; see the documentation ofreadFn
:https://github.com/ziglang/zig/blob/ab4c461b76ff7b1d10e6d2010370ea0984f97efe/lib/std/io.zig#L80-L83
This also means that wrapping the return of
xz.decompress
in abufferedReader
will almost always cause reading to fail, sincebufferedReader
relies on the end-of-stream-is-not-an-error behavior. Modifying this test case:https://github.com/ziglang/zig/blob/ab4c461b76ff7b1d10e6d2010370ea0984f97efe/lib/std/compress/xz/test.zig#L5-L12
like so:
will cause the
"compressed data"
test block to start failing.Expected Behavior
The tests above to pass
Some more context in this
#zig-help
Discord threadcc @FnControlOption @ianic since they've worked on
std.compress.xz