authorgravatar for squeek502@hotmail.comRyan Liptak <squeek502@hotmail.com> 2026-08-19 22:21:33-07:00
committergravatar for squeek502@hotmail.comRyan Liptak <squeek502@hotmail.com> 2026-08-20 13:09:16+02:00
log7eeb21f3a65ceabd2fce766c9a56bee68b92b380
tree47d2f29f267e794ef1fcead23a23561aaf854b3c
parent73b010e2216331b0b87240b05ea061294749383b

tls.Client: Fix reliance on rebase pointer stability that doesn't exist

This code relied on pointer stability within a Reader's buffer for `capacity` bytes after a `rebase` call. However, this is not something that `rebase` can guarantee (see https://codeberg.org/ziglang/zig/issues/36578). This eliminates the reliance on that behavior, but also eliminates the `rebase` call itself, since it's no longer necessary and effectively redundant. Closes https://codeberg.org/ziglang/zig/issues/36570

1 files changed, 6 insertions(+), 11 deletions(-)

lib/std/crypto/tls/Client.zig+6-11
......@@ -338,18 +338,13 @@ pub fn init(input: *Reader, output: *Writer, options: Options) InitError!Client
338338 var cleartext_fragment_end: usize = 0;
339339 var cleartext_bufs: [2][tls.max_ciphertext_inner_record_len]u8 = undefined;
340340 fragment: while (true) {
341 // Ensure the input buffer pointer is stable in this scope.
342 input.rebase(tls.max_ciphertext_record_len) catch |err| switch (err) {
343 error.EndOfStream => {}, // We have assurance the remainder of stream can be buffered.
344 error.ReadFailed => |e| return e,
345 };
346 const record_header = input.peek(tls.record_header_len) catch |err| switch (err) {
341 const record_header = (input.takeArray(tls.record_header_len) catch |err| switch (err) {
347342 error.EndOfStream => return error.TlsConnectionTruncated,
348343 error.ReadFailed => |e| return e,
349 };
350 const record_ct = input.takeEnumNonexhaustive(tls.ContentType, .big) catch unreachable; // already peeked
351 input.toss(2); // legacy_version
352 const record_len = input.takeInt(u16, .big) catch unreachable; // already peeked
344 }).*;
345 const record_ct: tls.ContentType = @fromBackingInt(record_header[0]);
346 // record_header[1..3] is legacy_version
347 const record_len = mem.readInt(u16, record_header[3..5], .big);
353348 if (record_len > tls.max_ciphertext_len) return error.TlsRecordOverflow;
354349 const record_buffer = input.take(record_len) catch |err| switch (err) {
355350 error.EndOfStream => return error.TlsConnectionTruncated,
......@@ -379,7 +374,7 @@ pub fn init(input: *Reader, output: *Writer, options: Options) InitError!Client
379374 const operand: V = pad ++ @as([8]u8, @bitCast(@byteSwap(read_seq)));
380375 break :nonce @as(V, pv.server_handshake_iv) ^ operand;
381376 };
382 P.AEAD.decrypt(cleartext, ciphertext, auth_tag, record_header, nonce, pv.server_handshake_key) catch
377 P.AEAD.decrypt(cleartext, ciphertext, auth_tag, &record_header, nonce, pv.server_handshake_key) catch
383378 return error.TlsBadRecordMac;
384379 // TODO use scalar, non-slice version
385380 const trimmed_len = mem.trimEnd(u8, cleartext, "\x00").len;