Commit graph

46 commits

Author SHA1 Message Date
Ryan Liptak
acd6ffdf69 Reader.peekDelimiterInclusive: Fix handling of stream implementations that return 0
Previously, the logic in peekDelimiterInclusive (when the delimiter was not found in the existing buffer) used the `n` returned from `r.vtable.stream` as the length of the slice to check, but it's valid for `vtable.stream` implementations to return 0 if they wrote to the buffer instead of `w`. In that scenario, the `indexOfScalarPos` would be given a 0-length slice so it would never be able to find the delimiter.

This commit changes the logic to assume that `r.vtable.stream` can both:
- return 0, and
- modify seek/end (i.e. it's also valid for a `vtable.stream` implementation to rebase)

Also introduces `std.testing.ReaderIndirect` which helps in being able to test against Reader implementations that return 0 from `stream`/`readVec`

Fixes #25428
2025-10-09 12:01:51 -07:00
Ryan Liptak
8d5b651c3a
Reader.defaultReadVec: Workaround bad r.end += r.vtable.stream() behavior
If `r.end` is updated in the `stream` implementation, then it's possible that `r.end += ...` will behave unexpectedly. What seems to happen is that it reverts back to its value before the function call and then the increment happens. Here's a reproduction:

```zig
test "fill when stream modifies `end` and returns 0" {
    var buf: [3]u8 = undefined;
    var zero_reader = infiniteZeroes(&buf);

    _ = try zero_reader.fill(1);
    try std.testing.expectEqual(buf.len, zero_reader.end);
}

pub fn infiniteZeroes(buf: []u8) std.Io.Reader {
    return .{
        .vtable = &.{
            .stream = stream,
        },
        .buffer = buf,
        .end = 0,
        .seek = 0,
    };
}

fn stream(r: *std.Io.Reader, _: *std.Io.Writer, _: std.Io.Limit) std.Io.Reader.StreamError!usize {
    @memset(r.buffer[r.seek..], 0);
    r.end = r.buffer.len;
    return 0;
}
```

When `fill` is called, it will call into `vtable.readVec` which in this case is `defaultReadVec`. In `defaultReadVec`:

- Before the `r.end += r.vtable.stream` line, `r.end` will be 0
- In `r.vtable.stream`, `r.end` is modified to 3 and it returns 0
- After the `r.end += r.vtable.stream` line, `r.end` will be 0 instead of the expected 3

Separating the `r.end += stream();` into two lines fixes the problem (and this separation is done elsewhere in `Reader` so it seems possible that this class of bug has been encountered before).

Potentially related issues:

- https://github.com/ziglang/zig/issues/4021
- https://github.com/ziglang/zig/issues/12064
2025-09-21 21:08:51 +02:00
Rohlem
6cdbf4223c never advance seek position in std.Io.Reader.peekDelimiterExclusive (#24899)
* extend std.Io.Reader.peekDelimiterExclusive test to repeat successful end-of-stream path (fails)

* fix std.Io.Reader.peekDelimiterExclusive to not advance seek position in successful end-of-stream path
2025-08-19 16:01:40 -07:00
Andrew Kelley
399bace2f2
Merge pull request #24874 from ziglang/tls-client
std: more reliable HTTP and TLS networking
2025-08-16 14:47:52 -07:00
Andrew Kelley
ef14c73245 Compilation: remove last instance of deprecatedReader
This also makes initStreaming preemptively disable file size checking.
2025-08-16 14:46:20 -07:00
Andrew Kelley
a0f9a5e78d std: more reliable HTTP and TLS networking
* std.Io.Reader: fix confused semantics of rebase. Before it was
  ambiguous whether it was supposed to be based on end or seek. Now it
  is clearly based on seek, with an added assertion for clarity.

* std.crypto.tls.Client: fix panic due to not enough buffer size
  available. Also, avoid unnecessary rebasing.

* std.http.Reader: introduce max_head_len to limit HTTP header length.
  This prevents crash in underlying reader which may require a minimum
  buffer length.

* std.http.Client: choose better buffer sizes for streams and TLS
  client. Crucially, the buffer shared by HTTP reader and TLS client
  needs to be big enough for all http headers *and* the max TLS record
  size. Bump HTTP header size default from 4K to 8K.

fixes #24872

I have noticed however that there are still fetch problems
2025-08-16 00:16:15 -07:00
Andrew Kelley
30b41dc510 std.compress.zstd.Decompress fixes
* std.Io.Reader: appendRemaining no longer supports alignment and has
  different rules about how exceeding limit. Fixed bug where it would
  return success instead of error.StreamTooLong like it was supposed to.

* std.Io.Reader: simplify appendRemaining and appendRemainingUnlimited
  to be implemented based on std.Io.Writer.Allocating

* std.Io.Writer: introduce unreachableRebase

* std.Io.Writer: remove minimum_unused_capacity from Allocating. maybe
  that flexibility could have been handy, but let's see if anyone
  actually needs it. The field is redundant with the superlinear growth
  of ArrayList capacity.

* std.Io.Writer: growingRebase also ensures total capacity on the
  preserve parameter, making it no longer necessary to do
  ensureTotalCapacity at the usage site of decompression streams.

* std.compress.flate.Decompress: fix rebase not taking into account seek

* std.compress.zstd.Decompress: split into "direct" and "indirect" usage
  patterns depending on whether a buffer is provided to init, matching
  how flate works. Remove some overzealous asserts that prevented buffer
  expansion from within rebase implementation.

* std.zig: fix readSourceFileToAlloc returning an overaligned slice
  which was difficult to free correctly.

fixes #24608
2025-08-15 10:44:35 -07:00
Andrew Kelley
1ba6838bc3
Merge pull request #24740 from ziglang/http-plus-fixes
fetch, tls, and http fixes
2025-08-08 12:33:53 -07:00
Igor Anić
3ea015db96 Io.Reader fix defaultReadVec
Running tar.pipeToFileSystem compressed_mingw_includes.tar file from #24732
finishes in infinite loop calling defaultReadVec with:
r.seek = 1024
r.end = 1024
r.buffer.len = 1024
first.len = 512
that combination calls vtable.stream with 0 capacity writer and loops
forever.

Comment is to use whichever has larger capacity, and this fix reflects that.
2025-08-08 12:28:00 -07:00
Andrew Kelley
8721efece4 std.crypto.tls.Client: always write to buffer
simplifies the logic & makes it respect limit
2025-08-07 19:55:40 -07:00
Andrew Kelley
abd76938cb std.Io.Reader: fix appendRemainingUnlimited
Now it avoids mutating `r` unnecessarily, allowing the `ending` Reader
to work.
2025-08-07 10:04:52 -07:00
Andrew Kelley
28190cc404 std.crypto.tls: rework for new std.Io API 2025-08-07 10:04:29 -07:00
Matthew Lugg
fd9cfc39f5
Merge pull request #24199 from Justus2308/24106-fmt-casts
zig fmt: canonicalize nested cast builtin order
2025-08-07 10:55:03 +01:00
Andrew Kelley
04fe1bfe3c std.Io.Reader: use readVec for fill functions
readVec has two updated responsibilities:
1. it must respect any existing already buffered data.
2. it must write to the buffer if data is empty
2025-08-06 21:23:06 -07:00
Justus Klausecker
7c35070b90 zig fmt: apply new cast builtin order 2025-08-03 14:59:56 +02:00
Andrew Kelley
165cd87c12 std.Io.Reader: don't set end to zero
because it may be used as a ring buffer
2025-07-31 22:10:11 -07:00
Andrew Kelley
111305678c std: match readVec fn prototype exactly
this is not necessary according to zig language, but works around a flaw
in the C backend
2025-07-31 22:10:11 -07:00
Andrew Kelley
c49c90a42a fetch: update API usage 2025-07-31 22:10:11 -07:00
Andrew Kelley
4c04835a08 std.compress.zstd.Decompress: implement discard and readVec 2025-07-31 22:10:11 -07:00
Andrew Kelley
05ce1f99a6 compiler: update to new flate API 2025-07-31 22:10:11 -07:00
Andrew Kelley
fa410cc234 std.Io: delete BitReader 2025-07-31 22:10:11 -07:00
Andrew Kelley
0294e91451 std.Io.Reader: fix readVec at end 2025-07-31 19:26:12 -07:00
Andrew Kelley
cf7a28febb std.Io.Reader: introduce readVec back into the VTable
simplifies and fixes things

addresses a subset of #24608
2025-07-30 09:26:34 -07:00
Andrew Kelley
1fcaf90dd3 std.Io.Reader: make fillUnbuffered respect prexisting buffer
addresses only one usage pattern in #24608
2025-07-29 23:10:50 -07:00
Andrew Kelley
04614d6ea1 std.Io.Reader: add rebase to the vtable
This eliminates a footgun and special case handling with fixed buffers,
as well as allowing decompression streams to keep a window in the output
buffer.
2025-07-26 20:00:25 -07:00
Andrew Kelley
7f1c04423e std.Io: add "preserve" variants to Reader/Writer 2025-07-25 14:15:33 -07:00
Andrew Kelley
3687eada6a std: rework zstd for new I/O API
This passes tests but it doesn't provide as big a window size as is
required to decompress larger streams.

The next commit in this branch will work towards that, without
introducing an additional buffer.
2025-07-25 14:15:33 -07:00
Andrew Kelley
b8955a2e0a std.Io.poll: update to new I/O API 2025-07-23 21:25:34 -07:00
Andrew Kelley
1dcea220a4 std.tar: update to new I/O API 2025-07-22 09:41:44 -07:00
Andrew Kelley
e4abdf5a13 std.Io.Reader: fix takeStruct/peekStruct packed
closes #24516
2025-07-20 11:23:12 -07:00
Andrew Kelley
8373788c4c
Merge pull request #24488 from ziglang/more
std.zig: finish updating to new I/O API
2025-07-20 11:24:41 +02:00
Andrew Kelley
c40fb96ca3 std.Io.Writer: fix writeSliceSwap
tried to be too clever, wrote bad code
2025-07-19 22:12:37 -07:00
Andrew Kelley
a288266f33 std.Io.Reader: remove aggressive assert from fill
with `.fixed("")` you should still be able to do `fill(1)` and have it
return error.EndOfStream.
2025-07-19 16:05:01 -07:00
Andrew Kelley
5784500572 std.Io.Reader: fix readSliceShort with smaller buffer than Reader
closes #24443
2025-07-17 09:26:31 -07:00
Andrew Kelley
86699acbb9 std.Io.Reader: update OneByteReader usage to std.testing.Reader 2025-07-17 09:26:31 -07:00
Andrew Kelley
70f514f1ba std.Io.Reader: fix appendRemaining harder
ensure that it issues a stream call that includes the buffer to detect
the end when needed, but otherwise does not offer Reader buffer to
append directly to the list.
2025-07-16 17:20:03 -07:00
Andrew Kelley
e7a639967e std.Io.Reader: fix appendRemaining
it calls readVec which is a higher level function than was expected in
the previous implementation
2025-07-16 17:20:03 -07:00
Andrew Kelley
f521aa0520 std.io.Reader: add more docs for rebase
closes #24418
2025-07-15 10:04:45 -07:00
Andrew Kelley
a5dbb656b1
Merge pull request #24454 from ziglang/packed-struct-streams
std.Io: handle packed structs better
2025-07-15 13:43:08 +02:00
Andrew Kelley
4f5fa959aa std.Io.Reader.streamDelimiterEnding docs clarification 2025-07-14 21:01:40 -07:00
Andrew Kelley
deb9f3e88f std.Io: handle packed structs better
Rather than having the endian-suffixed functions be the preferred ones
the unsuffixed ones are the preferred ones and the tricky functions get
a special suffix.

Makes packed structs read and written the same as integers.

closes #12960
2025-07-14 18:43:56 -07:00
Andrew Kelley
5496901e71 std.Io.Reader.appendRemaining: add missing assert 2025-07-14 00:14:21 -07:00
mlugg
549a466dd1 std.Io.Reader: encourage inlining hot buffer check
Resolves: #24424
2025-07-12 23:52:13 +02:00
mochalins
61eff7b6dd std: Fix Io.Reader.Limited and add test 2025-07-11 17:46:14 +02:00
Andrew Kelley
e255415498 std: add some missing doc comments 2025-07-10 16:52:29 -07:00
Andrew Kelley
5360968e03 std: rename io to Io in preparation
This commit is non-breaking.

std.io is deprecated in favor of std.Io, in preparation for that
namespace becoming an interface.
2025-07-11 01:16:27 +02:00
Renamed from lib/std/io/Reader.zig (Browse further)