mirror of
https://github.com/borgbackup/borg.git
synced 2026-10-12 02:11:36 +00:00
Merge pull request #10172 from ThomasWaldmann/reject-unc-paths-10164
Location: reject UNC paths everywhere early with a hint, fixes #10164
This commit is contained in:
@@ -12,6 +12,10 @@ expanded by your shell).
|
||||
|
||||
Note: You may also prepend ``file://`` to a filesystem path to use URL style.
|
||||
|
||||
Note: UNC paths (``//server/share/path``, ``\\server\share\path``) are not
|
||||
supported — mount the share (on Windows: map it to a drive letter, e.g.
|
||||
``net use X: \\server\share``) and use the mounted path instead.
|
||||
|
||||
**Remote repositories** accessed via SSH user@host (REST http over stdio):
|
||||
|
||||
``rest://user@host:port//abs/path/to/repo`` — absolute path
|
||||
|
||||
@@ -724,9 +724,9 @@ class Location:
|
||||
BORGSTORE_SCHEMES = ("sftp", "http", "https", "s3", "b2", "rclone")
|
||||
|
||||
# path may contain any chars. to avoid ambiguities with other regexes, it must not start with
|
||||
# "//", a "scheme://" or one of the borgstore "scheme:" specifiers (all of which are matched
|
||||
# a "scheme://" or one of the borgstore "scheme:" specifiers (all of which are matched
|
||||
# before local_re in _parse). the borgstore scheme list is sourced from BORGSTORE_SCHEMES.
|
||||
local_path_re = r"(?!(//|(?:ssh|file)://|(?:" + "|".join(BORGSTORE_SCHEMES) + r"):))" r"(?P<path>.+)"
|
||||
local_path_re = r"(?!((?:ssh|file)://|(?:" + "|".join(BORGSTORE_SCHEMES) + r"):))" r"(?P<path>.+)"
|
||||
|
||||
# abs_path must start with a slash (or drive letter on Windows).
|
||||
abs_path_re = r"(?P<path>[A-Za-z]:/.+)" if is_win32 else r"(?P<path>/.+)"
|
||||
@@ -796,11 +796,15 @@ class Location:
|
||||
|
||||
self.raw = text # as given by user, might contain placeholders
|
||||
self.processed = replace_placeholders(self.raw, overrides) # after placeholder replacement
|
||||
valid = self._parse(self.processed)
|
||||
if valid:
|
||||
self.valid = True
|
||||
else:
|
||||
if not self._parse(self.processed):
|
||||
raise ValueError('Invalid location format: "%s"' % self.processed)
|
||||
if self.proto == "file" and self.path.startswith("//"):
|
||||
# UNC path (//server/share/..., \\server\share\...): not supported, fail early with a hint, see #10164.
|
||||
raise ValueError(
|
||||
f'UNC paths are not supported: "{self.processed}". '
|
||||
"Mount the share (Windows: net use X: \\\\server\\share) and use the mounted path instead."
|
||||
)
|
||||
self.valid = True
|
||||
|
||||
def _parse(self, text):
|
||||
m = self.ssh_re.match(text)
|
||||
|
||||
@@ -264,13 +264,17 @@ class TestLocationWithoutEnv:
|
||||
repr(Location(url)) == f"Location(proto='file', user=None, pass=None, host=None, port=None, path='{path}')"
|
||||
)
|
||||
|
||||
@pytest.mark.skipif(is_win32, reason="still broken")
|
||||
def test_smb(self, monkeypatch):
|
||||
def test_unc_rejected(self, monkeypatch):
|
||||
# UNC paths are not supported (#3141), the parser rejects all spellings early, see #10164.
|
||||
monkeypatch.delenv("BORG_REPO", raising=False)
|
||||
assert (
|
||||
repr(Location("file:////server/share/path"))
|
||||
== "Location(proto='file', user=None, pass=None, host=None, port=None, path='//server/share/path')"
|
||||
)
|
||||
with pytest.raises(ValueError, match="UNC paths are not supported"):
|
||||
Location("//server/share/repo")
|
||||
# on win32, file:/// must be followed by a drive letter, so this is invalid even earlier.
|
||||
with pytest.raises(ValueError, match="Invalid location" if is_win32 else "UNC paths are not supported"):
|
||||
Location("file:////server/share/repo")
|
||||
if is_win32:
|
||||
with pytest.raises(ValueError, match="UNC paths are not supported"):
|
||||
Location(r"\\server\share\repo")
|
||||
|
||||
def test_folder(self, monkeypatch):
|
||||
monkeypatch.delenv("BORG_REPO", raising=False)
|
||||
|
||||
Reference in New Issue
Block a user