Ignore symbolic links pointing outside of the root directory (#339)

Fixes #338
This commit is contained in:
Neraste 2018-06-13 09:07:04 +02:00 committed by Łukasz Langa
parent fb34c9e195
commit 42a3fe5331
2 changed files with 58 additions and 2 deletions

View File

@ -2941,11 +2941,24 @@ def gen_python_files_in_dir(
"""Generate all files under `path` whose paths are not excluded by the
`exclude` regex, but are included by the `include` regex.
Symbolic links pointing outside of the root directory are ignored.
`report` is where output about exclusions goes.
"""
assert root.is_absolute(), f"INTERNAL ERROR: `root` must be absolute but is {root}"
for child in path.iterdir():
try:
normalized_path = "/" + child.resolve().relative_to(root).as_posix()
except ValueError:
if child.is_symlink():
report.path_ignored(
child,
"is a symbolic link that points outside of the root directory",
)
continue
raise
if child.is_dir():
normalized_path += "/"
exclude_match = exclude.search(normalized_path)

View File

@ -11,7 +11,7 @@
from tempfile import TemporaryDirectory
from typing import Any, BinaryIO, Generator, List, Tuple, Iterator
import unittest
from unittest.mock import patch
from unittest.mock import patch, MagicMock
from click import unstyle
from click.testing import CliRunner
@ -1162,6 +1162,49 @@ def test_assert_equivalent_different_asts(self) -> None:
with self.assertRaises(AssertionError):
black.assert_equivalent("{}", "None")
def test_symlink_out_of_root_directory(self) -> None:
# prepare argumens
path = MagicMock()
root = THIS_DIR
child = MagicMock()
include = re.compile(black.DEFAULT_INCLUDES)
exclude = re.compile(black.DEFAULT_EXCLUDES)
report = black.Report()
# set the behavior of mock arguments
# child should behave like a symlink which resolved path is clearly
# outside of the root directory
path.iterdir.return_value = [child]
child.resolve.return_value = Path("/a/b/c")
child.is_symlink.return_value = True
# call the method
# it should not raise any error
list(black.gen_python_files_in_dir(path, root, include, exclude, report))
# check the call of the methods of the mock objects
path.iterdir.assert_called_once()
child.resolve.assert_called_once()
child.is_symlink.assert_called_once()
# set the behavior of mock arguments
# child should behave like a strange file which resolved path is clearly
# outside of the root directory
child.is_symlink.return_value = False
# call the method
# it should raise a ValueError
with self.assertRaises(ValueError):
list(black.gen_python_files_in_dir(path, root, include, exclude, report))
# check the call of the methods of the mock objects
path.iterdir.assert_called()
self.assertEqual(path.iterdir.call_count, 2)
child.resolve.assert_called()
self.assertEqual(child.resolve.call_count, 2)
child.is_symlink.assert_called()
self.assertEqual(child.is_symlink.call_count, 2)
if __name__ == "__main__":
unittest.main(module="test_black")