##// END OF EJS Templates
dirstate-v2: Enforce data size read from the docket file...
Simon Sapin -
r48475:48aec076 default
parent child Browse files
Show More
@@ -637,7 +637,9 b' if rustmod is not None:'
637 data = self._opener.read(self.docket.data_filename())
637 data = self._opener.read(self.docket.data_filename())
638 else:
638 else:
639 data = b''
639 data = b''
640 self._rustmap = rustmod.DirstateMap.new_v2(data)
640 self._rustmap = rustmod.DirstateMap.new_v2(
641 data, self.docket.data_size
642 )
641 parents = self.docket.parents
643 parents = self.docket.parents
642 else:
644 else:
643 self._rustmap, parents = rustmod.DirstateMap.new_v1(
645 self._rustmap, parents = rustmod.DirstateMap.new_v1(
@@ -410,8 +410,15 b" impl<'on_disk> DirstateMap<'on_disk> {"
410 }
410 }
411
411
412 #[timed]
412 #[timed]
413 pub fn new_v2(on_disk: &'on_disk [u8]) -> Result<Self, DirstateError> {
413 pub fn new_v2(
414 Ok(on_disk::read(on_disk)?)
414 on_disk: &'on_disk [u8],
415 data_size: usize,
416 ) -> Result<Self, DirstateError> {
417 if let Some(data) = on_disk.get(..data_size) {
418 Ok(on_disk::read(data)?)
419 } else {
420 Err(DirstateV2ParseError.into())
421 }
415 }
422 }
416
423
417 #[timed]
424 #[timed]
@@ -21,7 +21,7 b' use bytes_cast::unaligned::{I32Be, I64Be'
21 use bytes_cast::BytesCast;
21 use bytes_cast::BytesCast;
22 use format_bytes::format_bytes;
22 use format_bytes::format_bytes;
23 use std::borrow::Cow;
23 use std::borrow::Cow;
24 use std::convert::TryFrom;
24 use std::convert::{TryFrom, TryInto};
25 use std::time::{Duration, SystemTime, UNIX_EPOCH};
25 use std::time::{Duration, SystemTime, UNIX_EPOCH};
26
26
27 /// Added at the start of `.hg/dirstate` when the "v2" format is used.
27 /// Added at the start of `.hg/dirstate` when the "v2" format is used.
@@ -224,6 +224,11 b" impl<'on_disk> Docket<'on_disk> {"
224 DirstateParents { p1, p2 }
224 DirstateParents { p1, p2 }
225 }
225 }
226
226
227 pub fn data_size(&self) -> usize {
228 // This `unwrap` could only panic on a 16-bit CPU
229 self.header.data_size.get().try_into().unwrap()
230 }
231
227 pub fn data_filename(&self) -> String {
232 pub fn data_filename(&self) -> String {
228 String::from_utf8(format_bytes!(b"dirstate.{}.d", self.uuid)).unwrap()
233 String::from_utf8(format_bytes!(b"dirstate.{}.d", self.uuid)).unwrap()
229 }
234 }
@@ -83,11 +83,12 b' py_class!(pub class DirstateMap |py| {'
83 @staticmethod
83 @staticmethod
84 def new_v2(
84 def new_v2(
85 on_disk: PyBytes,
85 on_disk: PyBytes,
86 data_size: usize,
86 ) -> PyResult<PyObject> {
87 ) -> PyResult<PyObject> {
87 let dirstate_error = |e: DirstateError| {
88 let dirstate_error = |e: DirstateError| {
88 PyErr::new::<exc::OSError, _>(py, format!("Dirstate error: {:?}", e))
89 PyErr::new::<exc::OSError, _>(py, format!("Dirstate error: {:?}", e))
89 };
90 };
90 let inner = OwningDirstateMap::new_v2(py, on_disk)
91 let inner = OwningDirstateMap::new_v2(py, on_disk, data_size)
91 .map_err(dirstate_error)?;
92 .map_err(dirstate_error)?;
92 let map = Self::create_instance(py, Box::new(inner))?;
93 let map = Self::create_instance(py, Box::new(inner))?;
93 Ok(map.into_object())
94 Ok(map.into_object())
@@ -48,9 +48,10 b' impl OwningDirstateMap {'
48 pub fn new_v2(
48 pub fn new_v2(
49 py: Python,
49 py: Python,
50 on_disk: PyBytes,
50 on_disk: PyBytes,
51 data_size: usize,
51 ) -> Result<Self, DirstateError> {
52 ) -> Result<Self, DirstateError> {
52 let bytes: &'_ [u8] = on_disk.data(py);
53 let bytes: &'_ [u8] = on_disk.data(py);
53 let map = DirstateMap::new_v2(bytes)?;
54 let map = DirstateMap::new_v2(bytes, data_size)?;
54
55
55 // Like in `bytes` above, this `'_` lifetime parameter borrows from
56 // Like in `bytes` above, this `'_` lifetime parameter borrows from
56 // the bytes buffer owned by `on_disk`.
57 // the bytes buffer owned by `on_disk`.
@@ -170,11 +170,13 b' pub fn run(invocation: &crate::CliInvoca'
170 let (mut dmap, parents) = if repo.has_dirstate_v2() {
170 let (mut dmap, parents) = if repo.has_dirstate_v2() {
171 let parents;
171 let parents;
172 let dirstate_data;
172 let dirstate_data;
173 let data_size;
173 if let Some(docket_data) =
174 if let Some(docket_data) =
174 repo.hg_vfs().read("dirstate").io_not_found_as_none()?
175 repo.hg_vfs().read("dirstate").io_not_found_as_none()?
175 {
176 {
176 let docket = on_disk::read_docket(&docket_data)?;
177 let docket = on_disk::read_docket(&docket_data)?;
177 parents = Some(docket.parents());
178 parents = Some(docket.parents());
179 data_size = docket.data_size();
178 dirstate_data_mmap = repo
180 dirstate_data_mmap = repo
179 .hg_vfs()
181 .hg_vfs()
180 .mmap_open(docket.data_filename())
182 .mmap_open(docket.data_filename())
@@ -182,9 +184,10 b' pub fn run(invocation: &crate::CliInvoca'
182 dirstate_data = dirstate_data_mmap.as_deref().unwrap_or(b"");
184 dirstate_data = dirstate_data_mmap.as_deref().unwrap_or(b"");
183 } else {
185 } else {
184 parents = None;
186 parents = None;
187 data_size = 0;
185 dirstate_data = b"";
188 dirstate_data = b"";
186 }
189 }
187 let dmap = DirstateMap::new_v2(dirstate_data)?;
190 let dmap = DirstateMap::new_v2(dirstate_data, data_size)?;
188 (dmap, parents)
191 (dmap, parents)
189 } else {
192 } else {
190 dirstate_data_mmap =
193 dirstate_data_mmap =
General Comments 0
You need to be logged in to leave comments. Login now