Skip to content

Commit 606121b

Browse files
committed
Do not fill_buf when BufReadIter.pos == limit
Otherwise synchronous reads may block. Fixes #157
1 parent 6c5302c commit 606121b

File tree

1 file changed

+52
-2
lines changed

1 file changed

+52
-2
lines changed

protobuf/src/buf_read_iter.rs

+52-2
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,7 @@ impl<'ignore> BufReadIter<'ignore> {
125125
debug_assert!(self.pos_of_buf_start + self.pos_within_buf as u64 <= self.limit);
126126
}
127127

128+
#[inline(always)]
128129
pub fn pos(&self) -> u64 {
129130
self.pos_of_buf_start + self.pos_within_buf as u64
130131
}
@@ -297,8 +298,9 @@ impl<'ignore> BufReadIter<'ignore> {
297298
fn do_fill_buf(&mut self) -> ProtobufResult<()> {
298299
debug_assert!(self.pos_within_buf == self.limit_within_buf);
299300

300-
// Limit is reached, so EOF is reached
301-
if self.limit_within_buf != self.buf.len() {
301+
// Limit is reached, do not fill buf, because otherwise
302+
// synchronous read from `CodedInputStream` may block.
303+
if self.limit == self.pos() {
302304
return Ok(());
303305
}
304306

@@ -384,3 +386,51 @@ mod test_bytes {
384386
}
385387

386388
}
389+
390+
#[cfg(test)]
391+
mod test {
392+
use super::*;
393+
use std::io::BufRead;
394+
use std::io::Read;
395+
use std::io;
396+
397+
#[test]
398+
fn eof_at_limit() {
399+
struct Read5ThenPanic {
400+
pos: usize,
401+
}
402+
403+
impl Read for Read5ThenPanic {
404+
fn read(&mut self, _buf: &mut [u8]) -> io::Result<usize> {
405+
unreachable!();
406+
}
407+
}
408+
409+
impl BufRead for Read5ThenPanic {
410+
fn fill_buf(&mut self) -> io::Result<&[u8]> {
411+
assert_eq!(0, self.pos);
412+
static ZERO_TO_FIVE: &'static [u8] = &[0, 1, 2, 3, 4];
413+
Ok(ZERO_TO_FIVE)
414+
}
415+
416+
fn consume(&mut self, amt: usize) {
417+
if amt == 0 {
418+
// drop of BufReadIter
419+
return;
420+
}
421+
422+
assert_eq!(0, self.pos);
423+
assert_eq!(5, amt);
424+
self.pos += amt;
425+
}
426+
}
427+
428+
let mut read = Read5ThenPanic { pos : 0 };
429+
let mut buf_read_iter = BufReadIter::from_buf_read(&mut read);
430+
assert_eq!(0, buf_read_iter.pos());
431+
let _prev_limit = buf_read_iter.push_limit(5);
432+
buf_read_iter.read_byte().expect("read_byte");
433+
buf_read_iter.read_exact(&mut [1, 2, 3, 4]).expect("read_exact");
434+
assert!(buf_read_iter.eof().expect("eof"));
435+
}
436+
}

0 commit comments

Comments
 (0)