Mercurial > hg
changeset 48543: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 |
files | rust/hg-core/src/revlog/index.rs rust/hg-core/src/revlog/revlog.rs |
diffstat | 2 files changed, 20 insertions(+), 13 deletions(-) [+] |
line wrap: on
line diff
--- a/rust/hg-core/src/revlog/index.rs Tue Dec 21 18:50:44 2021 +0100 +++ b/rust/hg-core/src/revlog/index.rs Tue Dec 21 21:23:46 2021 +0100 @@ -118,7 +118,7 @@ offset_override: None, }; - offset += INDEX_ENTRY_SIZE + entry.compressed_len(); + offset += INDEX_ENTRY_SIZE + entry.compressed_len() as usize; } if offset == bytes.len() { @@ -261,13 +261,13 @@ } /// Return the compressed length of the data. - pub fn compressed_len(&self) -> usize { - BigEndian::read_u32(&self.bytes[8..=11]) as usize + pub fn compressed_len(&self) -> u32 { + BigEndian::read_u32(&self.bytes[8..=11]) } /// Return the uncompressed length of the data. - pub fn uncompressed_len(&self) -> usize { - BigEndian::read_u32(&self.bytes[12..=15]) as usize + pub fn uncompressed_len(&self) -> i32 { + BigEndian::read_i32(&self.bytes[12..=15]) } /// Return the revision upon which the data has been derived.
--- a/rust/hg-core/src/revlog/revlog.rs Tue Dec 21 18:50:44 2021 +0100 +++ b/rust/hg-core/src/revlog/revlog.rs Tue Dec 21 21:23:46 2021 +0100 @@ -1,4 +1,5 @@ use std::borrow::Cow; +use std::convert::TryFrom; use std::io::Read; use std::ops::Deref; use std::path::Path; @@ -259,7 +260,7 @@ .get_entry(rev) .ok_or(RevlogError::InvalidRevision)?; let start = index_entry.offset(); - let end = start + index_entry.compressed_len(); + let end = start + index_entry.compressed_len() as usize; let data = if self.index.is_inline() { self.index.data(start, end) } else { @@ -300,8 +301,8 @@ revlog: &'a Revlog, rev: Revision, bytes: &'a [u8], - compressed_len: usize, - uncompressed_len: usize, + compressed_len: u32, + uncompressed_len: i32, base_rev_or_base_of_delta_chain: Option<Revision>, } @@ -310,6 +311,10 @@ self.rev } + pub fn uncompressed_len(&self) -> Option<u32> { + u32::try_from(self.uncompressed_len).ok() + } + /// The data for this entry, after resolving deltas if any. pub fn data(&self) -> Result<Cow<'a, [u8]>, HgError> { let mut entry = self.clone(); @@ -379,11 +384,12 @@ fn uncompressed_zlib_data(&self) -> Result<Vec<u8>, HgError> { let mut decoder = ZlibDecoder::new(self.bytes); if self.is_delta() { - let mut buf = Vec::with_capacity(self.compressed_len); + let mut buf = Vec::with_capacity(self.compressed_len as usize); decoder.read_to_end(&mut buf).map_err(|_| corrupted())?; Ok(buf) } else { - let mut buf = vec![0; self.uncompressed_len]; + let cap = self.uncompressed_len.max(0) as usize; + let mut buf = vec![0; cap]; decoder.read_exact(&mut buf).map_err(|_| corrupted())?; Ok(buf) } @@ -391,15 +397,16 @@ fn uncompressed_zstd_data(&self) -> Result<Vec<u8>, HgError> { if self.is_delta() { - let mut buf = Vec::with_capacity(self.compressed_len); + let mut buf = Vec::with_capacity(self.compressed_len as usize); zstd::stream::copy_decode(self.bytes, &mut buf) .map_err(|_| corrupted())?; Ok(buf) } else { - let mut buf = vec![0; self.uncompressed_len]; + let cap = self.uncompressed_len.max(0) as usize; + let mut buf = vec![0; cap]; let len = zstd::block::decompress_to_buffer(self.bytes, &mut buf) .map_err(|_| corrupted())?; - if len != self.uncompressed_len { + if len != self.uncompressed_len as usize { Err(corrupted()) } else { Ok(buf)