comparison rust/hg-core/src/revlog/revlog.rs @ 48572:0a4ac916673e

rhg: RevlogEntry::uncompressed_len is signed The corresponding Python code appears to explicitly check for non-negative values. Differential Revision: https://phab.mercurial-scm.org/D11962
author Simon Sapin <simon.sapin@octobus.net>
date Tue, 21 Dec 2021 21:23:46 +0100
parents 35c47015b9b7
children faa243f345cc
comparison
equal deleted inserted replaced
48571:35c47015b9b7 48572:0a4ac916673e
1 use std::borrow::Cow; 1 use std::borrow::Cow;
2 use std::convert::TryFrom;
2 use std::io::Read; 3 use std::io::Read;
3 use std::ops::Deref; 4 use std::ops::Deref;
4 use std::path::Path; 5 use std::path::Path;
5 6
6 use flate2::read::ZlibDecoder; 7 use flate2::read::ZlibDecoder;
257 let index_entry = self 258 let index_entry = self
258 .index 259 .index
259 .get_entry(rev) 260 .get_entry(rev)
260 .ok_or(RevlogError::InvalidRevision)?; 261 .ok_or(RevlogError::InvalidRevision)?;
261 let start = index_entry.offset(); 262 let start = index_entry.offset();
262 let end = start + index_entry.compressed_len(); 263 let end = start + index_entry.compressed_len() as usize;
263 let data = if self.index.is_inline() { 264 let data = if self.index.is_inline() {
264 self.index.data(start, end) 265 self.index.data(start, end)
265 } else { 266 } else {
266 &self.data()[start..end] 267 &self.data()[start..end]
267 }; 268 };
298 #[derive(Clone)] 299 #[derive(Clone)]
299 pub struct RevlogEntry<'a> { 300 pub struct RevlogEntry<'a> {
300 revlog: &'a Revlog, 301 revlog: &'a Revlog,
301 rev: Revision, 302 rev: Revision,
302 bytes: &'a [u8], 303 bytes: &'a [u8],
303 compressed_len: usize, 304 compressed_len: u32,
304 uncompressed_len: usize, 305 uncompressed_len: i32,
305 base_rev_or_base_of_delta_chain: Option<Revision>, 306 base_rev_or_base_of_delta_chain: Option<Revision>,
306 } 307 }
307 308
308 impl<'a> RevlogEntry<'a> { 309 impl<'a> RevlogEntry<'a> {
309 pub fn revision(&self) -> Revision { 310 pub fn revision(&self) -> Revision {
310 self.rev 311 self.rev
312 }
313
314 pub fn uncompressed_len(&self) -> Option<u32> {
315 u32::try_from(self.uncompressed_len).ok()
311 } 316 }
312 317
313 /// The data for this entry, after resolving deltas if any. 318 /// The data for this entry, after resolving deltas if any.
314 pub fn data(&self) -> Result<Cow<'a, [u8]>, HgError> { 319 pub fn data(&self) -> Result<Cow<'a, [u8]>, HgError> {
315 let mut entry = self.clone(); 320 let mut entry = self.clone();
377 } 382 }
378 383
379 fn uncompressed_zlib_data(&self) -> Result<Vec<u8>, HgError> { 384 fn uncompressed_zlib_data(&self) -> Result<Vec<u8>, HgError> {
380 let mut decoder = ZlibDecoder::new(self.bytes); 385 let mut decoder = ZlibDecoder::new(self.bytes);
381 if self.is_delta() { 386 if self.is_delta() {
382 let mut buf = Vec::with_capacity(self.compressed_len); 387 let mut buf = Vec::with_capacity(self.compressed_len as usize);
383 decoder.read_to_end(&mut buf).map_err(|_| corrupted())?; 388 decoder.read_to_end(&mut buf).map_err(|_| corrupted())?;
384 Ok(buf) 389 Ok(buf)
385 } else { 390 } else {
386 let mut buf = vec![0; self.uncompressed_len]; 391 let cap = self.uncompressed_len.max(0) as usize;
392 let mut buf = vec![0; cap];
387 decoder.read_exact(&mut buf).map_err(|_| corrupted())?; 393 decoder.read_exact(&mut buf).map_err(|_| corrupted())?;
388 Ok(buf) 394 Ok(buf)
389 } 395 }
390 } 396 }
391 397
392 fn uncompressed_zstd_data(&self) -> Result<Vec<u8>, HgError> { 398 fn uncompressed_zstd_data(&self) -> Result<Vec<u8>, HgError> {
393 if self.is_delta() { 399 if self.is_delta() {
394 let mut buf = Vec::with_capacity(self.compressed_len); 400 let mut buf = Vec::with_capacity(self.compressed_len as usize);
395 zstd::stream::copy_decode(self.bytes, &mut buf) 401 zstd::stream::copy_decode(self.bytes, &mut buf)
396 .map_err(|_| corrupted())?; 402 .map_err(|_| corrupted())?;
397 Ok(buf) 403 Ok(buf)
398 } else { 404 } else {
399 let mut buf = vec![0; self.uncompressed_len]; 405 let cap = self.uncompressed_len.max(0) as usize;
406 let mut buf = vec![0; cap];
400 let len = zstd::block::decompress_to_buffer(self.bytes, &mut buf) 407 let len = zstd::block::decompress_to_buffer(self.bytes, &mut buf)
401 .map_err(|_| corrupted())?; 408 .map_err(|_| corrupted())?;
402 if len != self.uncompressed_len { 409 if len != self.uncompressed_len as usize {
403 Err(corrupted()) 410 Err(corrupted())
404 } else { 411 } else {
405 Ok(buf) 412 Ok(buf)
406 } 413 }
407 } 414 }