59 Commits

Author SHA1 Message Date
Ryan Liptak
21f9f378f1 Reader.defaultDiscard: Fix for use with an indirect reader
If a Reader implementation implements `stream` by ignoring the Writer, writing directly to its internal buffer, and returning 0, then `defaultDiscard` would not update `seek` and also return 0, which is incorrect and can cause `discardShort` to violate the contract of `VTable.discard` by calling into `vtable.discard` with a non-empty buffer.

This commit fixes the problem by advancing seek up to the limit after the stream call. This logic could likely be somewhat simplified in the future depending on how #25170 is resolved.
2025-11-21 22:34:55 -08:00
Petr Pučil
38d44404a5 Fix param name in doc comment for std.Io.Reader.peek()
The old doc comment mentioned a parameter `len` three times, but the
function does not accept such a parameter - it is actually called `n`.
2025-11-08 00:34:41 -08:00
Andrew Kelley
d83d79c032 std.Io.Reader: rework peekDelimiterInclusive
Now it's based on calling fillMore rather than an illegal aliased stream
into the Reader buffer.

This commit also includes a disambiguation block inspired by #25162. If
`StreamTooLong` was added to `RebaseError` then this logic could be
replaced by removing the exit condition from the while loop. That error
code would represent when `buffer` capacity is too small for an
operation, replacing the current use of asserts.
2025-10-08 19:30:36 -07:00
mlugg
bf58b4e419 std.Io.Reader: fix delimiter bugs
Fix `takeDelimiter` and `takeDelimiterExclusive` tossing too many bytes
(#25132)

Also add/improve test coverage for all delimiter and sentinel methods,
update usages of `takeDelimiterExclusive` to not rely on the fixed bug,
tweak a handful of doc comments, and slightly simplify some logic.

I have not fixed #24950 in this commit because I am a little less
certain about the appropriate solution there.

Resolves: #25132

Co-authored-by: Andrew Kelley <andrew@ziglang.org>
2025-10-08 17:00:15 -07:00
Ryan Liptak
328ae41468 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-08 16:42:55 -07:00
Ryan Liptak
3fbb88c4bd 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-20 18:31:38 -07:00
Andrew Kelley
b7104231af
Merge pull request #25077 from ziglang/GenericReader
std.Io: delete GenericReader, AnyReader, FixedBufferStream; and related API breakage
2025-08-30 12:43:52 -07:00
Andrew Kelley
e2fdaea0b3 Revert "std.Io.Reader: work around llvm backend bug"
This reverts commit 530cc2c1111699d9d02ad9ebef94efa6b99f5205.

The compiler bug has been fixed.
2025-08-30 06:04:25 -07:00
Andrew Kelley
9a0970a12b rework std.Io.Writer.Allocating to support runtime-known alignment
Also, breaking API changes to:
* std.fs.Dir.readFileAlloc
* std.fs.Dir.readFileAllocOptions
2025-08-30 00:48:50 -07:00
Andrew Kelley
79f267f6b9 std.Io: delete GenericReader
and delete deprecated alias std.io
2025-08-29 17:14:26 -07:00
Andrew Kelley
43fbc37a49 std.debug.Pdb: migrate more towards new Reader API
There was some bug in this branch, and rather than diagnosing it, I
fully finished porting over to new Reader API. Did it fix the bug?
2025-08-28 22:41:06 -07:00
Andrew Kelley
530cc2c111 std.Io.Reader: work around llvm backend bug
tracked by #25067 and I already have a fix cooking in another branch
2025-08-28 18:30:57 -07:00
Andrew Kelley
8023f3dceb fix not discarding delimiter
perhaps these APIs have the defaults backwards, eh?
2025-08-28 18:30:57 -07:00
Andrew Kelley
f7884961c2 update more to avoid GenericWriter 2025-08-28 18:30:57 -07:00
Ryan Liptak
2b73c28cec Reader.appendRemaining: Take ownership of the full allocated slice
Before this commit, calling appendRemaining with an ArrayList where list.items.len != list.capacity could result in illegal behavior if the Writer.Allocating resized the list during the appendRemaining call.

Fixes #25057
2025-08-28 07:56:50 -07:00
Rohlem
81f5a7b8fd
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 11:19:02 -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