Skip to content
This repository has been archived by the owner on Aug 15, 2021. It is now read-only.

Commit

Permalink
IO Reader: Don't loop in 16k chunks
Browse files Browse the repository at this point in the history
The splitting of reads into 16k chunks to avoid resource exhaustion has
become obsolete since .take() / .read_to_end() is used, as its
implementation already takes care of allocating in sane chunk sizes.

The .reserve() call for the small values ensures that we use the
available knowledge in the typical cases.

(Given indenting changes, this commit is best viewed with
--ignore-all-space).
  • Loading branch information
chrysn committed Nov 17, 2018
1 parent b8e504b commit a9ec6ae
Showing 1 changed file with 23 additions and 32 deletions.
55 changes: 23 additions & 32 deletions src/read.rs
Original file line number Diff line number Diff line change
Expand Up @@ -113,42 +113,33 @@ where
scratch_offset: usize,
) -> Result<Reference<'de>> {
assert!(scratch.len() == scratch_offset);
while n > 0 {
// defend against malicious input pretending to be huge strings by limiting growth
let mut to_read = cmp::min(n, 16 * 1024);
n -= to_read;

scratch.reserve(to_read);
// defend against malicious input pretending to be huge strings by limiting growth
scratch.reserve(cmp::min(n, 16 * 1024));

if let Some(ch) = self.ch.take() {
scratch.push(ch);
to_read -= 1;
}

let transfer_result = {
// Prepare for take() (which consumes its reader) by creating a reference adaptor
// that'll only live in this block
let reference = self.reader.by_ref();
// Append the first to_read bytes of the reader to the scratch vector (or up to
// an error or EOF indicated by a shorter read)
let mut taken = reference.take(to_read as u64);
taken.read_to_end(scratch)
};
match transfer_result {
Ok(r) if r == to_read => (),
Ok(_) => {
return Err(Error::syntax(
ErrorCode::EofWhileParsingValue,
self.offset(),
));
},
Err(e) => {
return Err(Error::io(e))
}
}
if let Some(ch) = self.ch.take() {
scratch.push(ch);
n -= 1;
}

Ok(Reference::Copied)
let transfer_result = {
// Prepare for take() (which consumes its reader) by creating a reference adaptor
// that'll only live in this block
let reference = self.reader.by_ref();
// Append the first n bytes of the reader to the scratch vector (or up to
// an error or EOF indicated by a shorter read)
let mut taken = reference.take(n as u64);
taken.read_to_end(scratch)
};

match transfer_result {
Ok(r) if r == n => Ok(Reference::Copied),
Ok(_) => Err(Error::syntax(
ErrorCode::EofWhileParsingValue,
self.offset(),
)),
Err(e) => Err(Error::io(e)),
}
}

fn read_into(&mut self, buf: &mut [u8]) -> Result<()> {
Expand Down

0 comments on commit a9ec6ae

Please sign in to comment.