D7921: rust-dirs-multiset: improve temporary error message
Alphare (Raphaël Gomès)
phabricator at mercurial-scm.org
Fri Jan 17 10:42:27 UTC 2020
Alphare created this revision.
Herald added subscribers: mercurial-devel, kevincox, durin42.
Herald added a reviewer: hg-reviewers.
REVISION SUMMARY
While we wait on a future patch that could verify that the paths passed to
`DirsMultiset` have been audited, we still need to handle this error.
This patch makes it easier to bubble up and makes the error clearer.
Also, this patch introduces the `subslice_index` function that could be useful
for other - albeit niche - purposes.
REPOSITORY
rHG Mercurial
BRANCH
default
REVISION DETAIL
https://phab.mercurial-scm.org/D7921
AFFECTED FILES
rust/hg-core/src/dirstate/dirs_multiset.rs
rust/hg-core/src/lib.rs
rust/hg-core/src/utils.rs
CHANGE DETAILS
diff --git a/rust/hg-core/src/utils.rs b/rust/hg-core/src/utils.rs
--- a/rust/hg-core/src/utils.rs
+++ b/rust/hg-core/src/utils.rs
@@ -61,6 +61,36 @@
}
}
+/// Find the offset of the subslice relative to the original collection
+///
+/// This function panics for zero-sized types.
+/// # Examples:
+///
+/// ```
+/// use crate::hg::utils::subslice_offset;
+/// let mut line = b"Subslice me!".to_vec();
+/// assert_eq!(subslice_offset(&line, &line[8..]), Some(8));
+///
+/// assert_eq!(subslice_offset(&line, b"hahaha"), None);
+///
+/// // Empty array
+/// let v: [u8; 0] = [];
+/// assert_eq!(subslice_offset(&v, &v), Some(0));
+/// assert_eq!(subslice_offset(&v, b"hehe"), None);
+/// ```
+pub fn subslice_offset<T: Sized>(outer: &[T], inner: &[T]) -> Option<usize> {
+ let pointee_size = std::mem::size_of::<T>();
+ assert!(0 < pointee_size && pointee_size <= isize::max_value() as usize);
+
+ let outer_start = outer.as_ptr() as usize;
+ let inner = inner.as_ptr() as usize;
+ if inner < outer_start || inner > outer_start.wrapping_add(outer.len()) {
+ None
+ } else {
+ Some(inner.wrapping_sub(outer_start))
+ }
+}
+
pub trait SliceExt {
fn trim_end(&self) -> &Self;
fn trim_start(&self) -> &Self;
diff --git a/rust/hg-core/src/lib.rs b/rust/hg-core/src/lib.rs
--- a/rust/hg-core/src/lib.rs
+++ b/rust/hg-core/src/lib.rs
@@ -82,18 +82,17 @@
pub enum DirstateMapError {
PathNotFound(HgPathBuf),
EmptyPath,
- ConsecutiveSlashes,
+ InvalidPath(HgPathError),
}
impl ToString for DirstateMapError {
fn to_string(&self) -> String {
- use crate::DirstateMapError::*;
match self {
- PathNotFound(_) => "expected a value, found none".to_string(),
- EmptyPath => "Overflow in dirstate.".to_string(),
- ConsecutiveSlashes => {
- "found invalid consecutive slashes in path".to_string()
+ DirstateMapError::PathNotFound(_) => {
+ "expected a value, found none".to_string()
}
+ DirstateMapError::EmptyPath => "Overflow in dirstate.".to_string(),
+ DirstateMapError::InvalidPath(e) => e.to_string(),
}
}
}
diff --git a/rust/hg-core/src/dirstate/dirs_multiset.rs b/rust/hg-core/src/dirstate/dirs_multiset.rs
--- a/rust/hg-core/src/dirstate/dirs_multiset.rs
+++ b/rust/hg-core/src/dirstate/dirs_multiset.rs
@@ -8,6 +8,8 @@
//! A multiset of directory names.
//!
//! Used to counts the references to directories in a manifest or dirstate.
+use crate::utils::hg_path::HgPathError;
+use crate::utils::subslice_offset;
use crate::{
dirstate::EntryState,
utils::{
@@ -78,7 +80,18 @@
if subpath.as_bytes().last() == Some(&b'/') {
// TODO Remove this once PathAuditor is certified
// as the only entrypoint for path data
- return Err(DirstateMapError::ConsecutiveSlashes);
+ let offset = subslice_offset(
+ path.as_ref().as_bytes(),
+ subpath.as_bytes(),
+ );
+ let second_slash_index = offset.unwrap() + subpath.len() - 1;
+
+ return Err(DirstateMapError::InvalidPath(
+ HgPathError::ConsecutiveSlashes {
+ bytes: path.as_ref().as_bytes().to_owned(),
+ second_slash_index,
+ },
+ ));
}
if let Some(val) = self.inner.get_mut(subpath) {
*val += 1;
To: Alphare, #hg-reviewers
Cc: durin42, kevincox, mercurial-devel
More information about the Mercurial-devel
mailing list