From 4138c864a4bb6c95a9d40c694a6654136f584892 Mon Sep 17 00:00:00 2001 From: Sai Asish Y Date: Wed, 13 May 2026 13:58:53 -0700 Subject: [PATCH 1/2] test: capture try_read panic on multi-byte input --- src/reader.rs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/reader.rs b/src/reader.rs index e8e3e984..f88a9422 100644 --- a/src/reader.rs +++ b/src/reader.rs @@ -457,4 +457,16 @@ mod tests { assert_eq!(None, r.try_read()); assert_eq!(None, r.try_read()); } + + #[test] + #[should_panic(expected = "is_char_boundary")] + fn test_try_read_multibyte() { + // Reproduces the char-boundary panic when the buffer holds a + // multi-byte UTF-8 char. Filling `buffer` directly keeps the + // test fully synchronous. + let f = io::Cursor::new(""); + let mut r = NBReader::new(f, Options::default()); + r.buffer.push_str("\u{c3}\u{83}"); + let _ = r.try_read(); + } } From 740defa68bf5c8a335c9f7551f6f44dd9e02893c Mon Sep 17 00:00:00 2001 From: Sai Asish Y Date: Wed, 13 May 2026 13:59:18 -0700 Subject: [PATCH 2/2] fix: avoid char-boundary panic in NBReader::try_read --- src/reader.rs | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/src/reader.rs b/src/reader.rs index f88a9422..b15feeb4 100644 --- a/src/reader.rs +++ b/src/reader.rs @@ -203,11 +203,9 @@ impl NBReader { pub fn try_read(&mut self) -> Option { // discard eventual errors, EOF will be handled in read_until correctly let _ = self.read_into_buffer(); - if !self.buffer.is_empty() { - self.buffer.drain(..1).last() - } else { - None - } + let first = self.buffer.chars().next()?; + self.buffer.drain(..first.len_utf8()); + Some(first) } } @@ -459,14 +457,13 @@ mod tests { } #[test] - #[should_panic(expected = "is_char_boundary")] fn test_try_read_multibyte() { - // Reproduces the char-boundary panic when the buffer holds a - // multi-byte UTF-8 char. Filling `buffer` directly keeps the - // test fully synchronous. + // Filling `buffer` directly keeps the test fully synchronous. let f = io::Cursor::new(""); let mut r = NBReader::new(f, Options::default()); r.buffer.push_str("\u{c3}\u{83}"); - let _ = r.try_read(); + assert_eq!(Some('\u{c3}'), r.try_read()); + assert_eq!(Some('\u{83}'), r.try_read()); + assert_eq!(None, r.try_read()); } }