| 264 | } |
| 265 | |
| 266 | fn read_block_next(&mut self) -> Result<(), AvroError> { |
| 267 | assert!(self.is_empty(), "Expected self to be empty!"); |
| 268 | match util::read_long(&mut self.inner) { |
| 269 | Ok(block_len) => { |
| 270 | // The object count is read straight from the wire; cap it like |
| 271 | // every other wire-read length (and reject negatives, which wrap |
| 272 | // to a huge `usize`). Otherwise a crafted block with a huge count |
| 273 | // and a zero-byte schema (e.g. `null`) makes the reader spin |
| 274 | // decoding billions of empty values. Found by the reader_decode |
| 275 | // cargo-fuzz target. |
| 276 | self.messages_remaining = util::safe_len(block_len as usize)?; |
| 277 | let block_bytes = util::safe_len(util::read_long(&mut self.inner)? as usize)?; |
| 278 | self.fill_buf(block_bytes)?; |
| 279 | let mut marker = [0u8; 16]; |
| 280 | self.inner.read_exact(&mut marker)?; |
| 281 | |
| 282 | if marker != self.header.marker { |
| 283 | return Err(DecodeError::MismatchedBlockHeader { |
| 284 | expected: self.header.marker, |
| 285 | actual: marker, |
| 286 | } |
| 287 | .into()); |
| 288 | } |
| 289 | |
| 290 | // NOTE (JAB): This doesn't fit this Reader pattern very well. |
| 291 | // `self.buf` is a growable buffer that is reused as the reader is iterated. |
| 292 | // For non `Codec::Null` variants, `decompress` will allocate a new `Vec` |
| 293 | // and replace `buf` with the new one, instead of reusing the same buffer. |
| 294 | // We can address this by using some "limited read" type to decode directly |
| 295 | // into the buffer. But this is fine, for now. |
| 296 | self.header.codec.decompress(&mut self.buf)?; |
| 297 | |
| 298 | Ok(()) |
| 299 | } |
| 300 | Err(e) => { |
| 301 | if let AvroError::IO(std::io::ErrorKind::UnexpectedEof) = e { |
| 302 | // to not return any error in case we only finished to read cleanly from the stream |
| 303 | Ok(()) |
| 304 | } else { |
| 305 | Err(e) |
| 306 | } |
| 307 | } |
| 308 | } |
| 309 | } |
| 310 | } |
| 311 | |
| 312 | impl<R: AvroRead> Iterator for Reader<R> { |