"""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():
-        normalized_path = "/" + child.resolve().relative_to(root).as_posix()
+        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)
 
 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
         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")