dirstate: block addition of paths containing "." and ".."

Summary:
Mergedrivers can call dirstate.add directly and are adding paths with
"." and "..". Let's block those paths.

Reviewed By: quark-zju

Differential Revision: D23375469

fbshipit-source-id: 64e9f20169cfd50325ecd8ebcc1dd3be7a5cb202
This commit is contained in:
Durham Goode 2020-08-28 09:39:34 -07:00 committed by Facebook GitHub Bot
parent 3adb4358ae
commit 08c938e859
5 changed files with 26 additions and 4 deletions

View File

@ -577,6 +577,10 @@ class dirstate(object):
raise error.Abort(
_("cannot add non-root-relative path to dirstate: %s") % f
)
relativedirs = [".", ".."]
if any(s for s in f.split("/") if s in relativedirs):
raise error.Abort(_("cannot add path with relative parents: %s") % f)
# shadows
for d in util.finddirs(f):
if self._map.hastrackeddir(d):

View File

@ -9,6 +9,7 @@ anyhow = "1.0.20"
bitflags = "1.0.4"
byteorder = "1.2.7"
thiserror = "1.0.5"
types = { path = "../types" }
twox-hash = "*"
vlqencoding = { version = "0.1.0", path = "../vlqencoding" }

View File

@ -17,6 +17,8 @@ use std::cell::Cell;
use std::collections::Bound;
use std::io::{Cursor, Read, Write};
use types::RepoPath;
/// A node entry is an entry in a directory, either a file or another directory.
#[derive(Debug)]
pub(crate) enum NodeEntry<T> {
@ -609,6 +611,8 @@ where
/// Add a file to the node. The name may contain a path, in which case sufficient
/// subdirectories are updated to add or update the file.
fn add(&mut self, store: &dyn StoreView, name: KeyRef, info: &T) -> Result<bool> {
// Construct a RepoPath so we match the core path validation logic.
let _ = RepoPath::from_utf8(name)?;
let (new_entry, file_added) = match self.path_recurse(store, name)? {
PathRecurse::Directory(_dir, path, node) => {
// The file is in a subdirectory. Add it to the subdirectory.

View File

@ -210,9 +210,8 @@ mod tests {
}
// Some random paths extracted from fb-hgext, plus some manually added entries, shuffled.
const SAMPLE_PATHS: [&[u8]; 22] = [
const SAMPLE_PATHS: [&[u8]; 21] = [
b".fbarcanist",
b"build/.",
b"phabricator/phabricator_graphql_client_urllib.pyc",
b"hgext3rd/__init__.py",
b"hgext3rd/.git/objects/14/8f179e7e702ddedb54c53f2726e7f81b14a33f",
@ -303,8 +302,8 @@ mod tests {
let dir = TempDir::new("treestate").expect("tempdir");
let mut state = new_treestate(dir.path().join("1"));
assert!(state.has_dir(b"/").unwrap());
assert!(state.has_dir(b"build/").unwrap());
assert!(!state.has_dir(b"build2/").unwrap());
assert!(state.has_dir(b"hgext3rd/").unwrap());
assert!(!state.has_dir(b"hgext4th/").unwrap());
assert!(state.has_dir(b"rust/radixbuf/.git/objects/").unwrap());
assert!(!state.has_dir(b"rust/radixbuf/.git2/objects/").unwrap());
}

View File

@ -93,3 +93,17 @@ Verify that status reports deleted files correctly
$ hg status
! a
$ hg diff
Dirstate should block addition of paths with relative parent components
$ hg up -C .
0 files updated, 0 files merged, 0 files removed, 0 files unresolved
$ ls
$ hg debugsh -c "repo.dirstate.add('foo/../b')"
abort: cannot add path with relative parents: foo/../b
[255]
$ touch b
$ mkdir foo
$ hg add foo/../b
$ hg commit -m "add b"
$ hg status --change .
A b