Browse Source

safe_join on Windows uses posixpath

fixes #2033
closes #2059
pull/2401/head
David Lord 7 years ago committed by Markus Unterwaditzer
parent
commit
f7c35bf0d5
  1. 7
      CHANGES
  2. 22
      flask/helpers.py
  3. 25
      tests/test_helpers.py

7
CHANGES

@ -15,6 +15,13 @@ Major release, unreleased
method returns compressed response by default, and pretty response in method returns compressed response by default, and pretty response in
debug mode. debug mode.
Version 0.12.2
--------------
Bugfix release
- Fix a bug in `safe_join` on Windows.
Version 0.12.1 Version 0.12.1
-------------- --------------

22
flask/helpers.py

@ -619,18 +619,24 @@ def safe_join(directory, *pathnames):
:raises: :class:`~werkzeug.exceptions.NotFound` if one or more passed :raises: :class:`~werkzeug.exceptions.NotFound` if one or more passed
paths fall out of its boundaries. paths fall out of its boundaries.
""" """
parts = [directory]
for filename in pathnames: for filename in pathnames:
if filename != '': if filename != '':
filename = posixpath.normpath(filename) filename = posixpath.normpath(filename)
for sep in _os_alt_seps:
if sep in filename: if (
raise NotFound() any(sep in filename for sep in _os_alt_seps)
if os.path.isabs(filename) or \ or os.path.isabs(filename)
filename == '..' or \ or filename == '..'
filename.startswith('../'): or filename.startswith('../')
):
raise NotFound() raise NotFound()
directory = os.path.join(directory, filename)
return directory parts.append(filename)
return posixpath.join(*parts)
def send_from_directory(directory, filename, **options): def send_from_directory(directory, filename, **options):

25
tests/test_helpers.py

@ -846,21 +846,20 @@ class TestStreaming(object):
class TestSafeJoin(object): class TestSafeJoin(object):
def test_safe_join(self): def test_safe_join(self):
# Valid combinations of *args and expected joined paths. # Valid combinations of *args and expected joined paths.
passing = ( passing = (
(('a/b/c', ), 'a/b/c'), (('a/b/c',), 'a/b/c'),
(('/', 'a/', 'b/', 'c/', ), '/a/b/c'), (('/', 'a/', 'b/', 'c/'), '/a/b/c'),
(('a', 'b', 'c', ), 'a/b/c'), (('a', 'b', 'c'), 'a/b/c'),
(('/a', 'b/c', ), '/a/b/c'), (('/a', 'b/c'), '/a/b/c'),
(('a/b', 'X/../c'), 'a/b/c', ), (('a/b', 'X/../c'), 'a/b/c'),
(('/a/b', 'c/X/..'), '/a/b/c', ), (('/a/b', 'c/X/..'), '/a/b/c'),
# If last path is '' add a slash # If last path is '' add a slash
(('/a/b/c', '', ), '/a/b/c/', ), (('/a/b/c', ''), '/a/b/c/'),
# Preserve dot slash # Preserve dot slash
(('/a/b/c', './', ), '/a/b/c/.', ), (('/a/b/c', './'), '/a/b/c/.'),
(('a/b/c', 'X/..'), 'a/b/c/.', ), (('a/b/c', 'X/..'), 'a/b/c/.'),
# Base directory is always considered safe # Base directory is always considered safe
(('../', 'a/b/c'), '../a/b/c'), (('../', 'a/b/c'), '../a/b/c'),
(('/..', ), '/..'), (('/..', ), '/..'),
@ -874,12 +873,12 @@ class TestSafeJoin(object):
failing = ( failing = (
# path.isabs and ``..'' checks # path.isabs and ``..'' checks
('/a', 'b', '/c'), ('/a', 'b', '/c'),
('/a', '../b/c', ), ('/a', '../b/c'),
('/a', '..', 'b/c'), ('/a', '..', 'b/c'),
# Boundaries violations after path normalization # Boundaries violations after path normalization
('/a', 'b/../b/../../c', ), ('/a', 'b/../b/../../c'),
('/a', 'b', 'c/../..'), ('/a', 'b', 'c/../..'),
('/a', 'b/../../c', ), ('/a', 'b/../../c'),
) )
for args in failing: for args in failing:

Loading…
Cancel
Save