Commit 03936e1d by btimby

Use explicit exception to detect invalid path (BackReferenceError), see comments on r773

parent 34c78ce2
...@@ -188,6 +188,11 @@ class NoMMapError(ResourceError): ...@@ -188,6 +188,11 @@ class NoMMapError(ResourceError):
default_message = "Can't get mmap for %(path)s" default_message = "Can't get mmap for %(path)s"
class BackReferenceError(FSError, ValueError):
"""Exception raised when too many backrefs exist in a path (ex: '/..', '/docs/../..')."""
default_message = "Too many backrefs in '%(path)s'"
def convert_fs_errors(func): def convert_fs_errors(func):
"""Function wrapper to convert FSError instances into OSError.""" """Function wrapper to convert FSError instances into OSError."""
@wraps(func) @wraps(func)
......
...@@ -185,12 +185,10 @@ class SFTPServerInterface(paramiko.SFTPServerInterface): ...@@ -185,12 +185,10 @@ class SFTPServerInterface(paramiko.SFTPServerInterface):
def canonicalize(self, path): def canonicalize(self, path):
try: try:
return abspath(normpath(path)).encode(self.encoding) return abspath(normpath(path)).encode(self.encoding)
except ValueError, e: except BackReferenceError:
# If the client tries to use backrefs to escape root, gently # If the client tries to use backrefs to escape root, gently
# nudge them back to /. # nudge them back to /.
if 'too many backrefs' in e.args[0]:
return '/' return '/'
raise
@report_sftp_errors @report_sftp_errors
def chattr(self, path, attr): def chattr(self, path, attr):
......
...@@ -33,7 +33,7 @@ def normpath(path): ...@@ -33,7 +33,7 @@ def normpath(path):
>>> normpath("foo/../../bar") >>> normpath("foo/../../bar")
Traceback (most recent call last) Traceback (most recent call last)
... ...
ValueError: too many backrefs in path 'foo/../../bar' BackReferenceError: Too many backrefs in 'foo/../../bar'
""" """
...@@ -57,7 +57,10 @@ def normpath(path): ...@@ -57,7 +57,10 @@ def normpath(path):
else: else:
append(component) append(component)
except IndexError: except IndexError:
raise ValueError("too many backrefs in path '%s'" % path) # Imported here because errors imports this module (path),
# causing a circular import.
from fs.errors import BackReferenceError
BackReferenceError(details={ 'path': path })
if path[0] == '/': if path[0] == '/':
return '/%s' % '/'.join(components) return '/%s' % '/'.join(components)
return '/'.join(components) return '/'.join(components)
...@@ -78,6 +81,7 @@ def iteratepath(path, numsplits=None): ...@@ -78,6 +81,7 @@ def iteratepath(path, numsplits=None):
else: else:
return path.split('/', numsplits) return path.split('/', numsplits)
def recursepath(path, reverse=False): def recursepath(path, reverse=False):
"""Returns intermediate paths from the root to the given path """Returns intermediate paths from the root to the given path
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment