diff --git a/src/lib.rs b/src/lib.rs index 0434a64..415e379 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -53,14 +53,18 @@ impl<'de> dec::Read<'de> for SliceReader<'de> { #[inline] fn fill<'b>(&'b mut self, want: usize) -> Result, Self::Error> { - let len = core::cmp::min(self.buf.len(), want); - Ok(dec::Reference::Long(&self.buf[..len])) + let buf = self.buf; + let buf_len = buf.len(); + let len = if buf_len < want { buf_len } else { want }; + Ok(dec::Reference::Long(&buf[..len])) } #[inline] fn advance(&mut self, n: usize) { - let len = core::cmp::min(self.buf.len(), n); - self.buf = &self.buf[len..]; + let buf = self.buf; + let buf_len = buf.len(); + let len = if buf_len < n { buf_len } else { n }; + self.buf = &buf[len..]; } } @@ -429,18 +433,35 @@ where let mut shift = 0; loop { - let byte = - peek_one(r).map_err(|_| anyhow!("Unexpected EOF while reading ULEB128 number."))?; - r.advance(1); + // Read up to 10 bytes at once (max length of u64 LEB128) + let reference = r + .fill(10) + .map_err(|_| anyhow!("Unexpected EOF while reading ULEB128 number."))?; + let buf = reference.as_ref(); + + if buf.is_empty() { + return Err(anyhow!("Unexpected EOF while reading ULEB128 number.")); + } - if (byte & 0x80) == 0 { - result |= (byte as u64) << shift; - return Ok(result); - } else { - result |= (byte as u64 & 0x7F) << shift; + let mut consumed = 0; + for &byte in buf { + consumed += 1; + + if (byte & 0x80) == 0 { + result |= (byte as u64) << shift; + r.advance(consumed); + return Ok(result); + } else { + result |= (byte as u64 & 0x7F) << shift; + shift += 7; + if shift >= 64 { + return Err(anyhow!("ULEB128 is too large for u64")); + } + } } - shift += 7; + // All bytes in this chunk had continuation bit set; advance and continue + r.advance(consumed); } }