From 83c3305863d38291c4905657e27552ecac435fcf Mon Sep 17 00:00:00 2001 From: edef Date: Fri, 9 May 2025 16:56:08 +0000 Subject: [PATCH] fix(nix-compat/wire/bytes/reader): handle zero cases Legitimate zero-length reads could cause spurious unexpected EOF, since we implicitly assumed buffers always have remaining capacity. For the buffered case, `consume(0)` could cause panics after either `poll_fill_buf` or `poll_read` had returned `Poll::Pending`. The bytes_read/with_limited logic receives a stylistic cleanup to make it obvious that bytes_read is always written before being used. Change-Id: I46aa47113309552dcef9532b5d4009d2186db9cd Reviewed-on: https://cl.snix.dev/c/snix/+/30492 Tested-by: besadii Reviewed-by: Brian Olsen Reviewed-by: Florian Klink --- snix/nix-compat/src/wire/bytes/reader/mod.rs | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/snix/nix-compat/src/wire/bytes/reader/mod.rs b/snix/nix-compat/src/wire/bytes/reader/mod.rs index a6209a6e6..6939fe9d4 100644 --- a/snix/nix-compat/src/wire/bytes/reader/mod.rs +++ b/snix/nix-compat/src/wire/bytes/reader/mod.rs @@ -129,6 +129,11 @@ impl AsyncRead for BytesReader { ) -> Poll> { let this = &mut self.state; + // reading nothing always succeeds + if buf.remaining() == 0 { + return Ok(()).into(); + } + loop { match this { State::Body { @@ -147,11 +152,8 @@ impl AsyncRead for BytesReader { Pin::new(reader.as_mut().unwrap()) }; - let mut bytes_read = 0; - ready!(with_limited(buf, remaining, |buf| { - let ret = reader.poll_read(cx, buf); - bytes_read = buf.filled().len(); - ret + let bytes_read = ready!(with_limited(buf, remaining, |buf| { + reader.poll_read(cx, buf).map_ok(|()| buf.filled().len()) }))?; *consumed += bytes_read as u64; @@ -262,7 +264,11 @@ impl AsyncBufRead for BytesReader { reader.consume(amt); } - State::ReadTrailer(_) => unreachable!(), + State::ReadTrailer(_) => { + if amt != 0 { + unreachable!(); + } + } State::ReleaseTrailer { consumed, data } => { *consumed = amt .checked_add(*consumed as usize)