From ae9ed4f582d36653b947ded51d68b9c633ab112f Mon Sep 17 00:00:00 2001 From: mrbean-bremen Date: Wed, 4 Apr 2018 19:22:51 +0200 Subject: [PATCH] Raise OSError in os.readlink if path ends with separator - fixes #359 --- CHANGES.md | 7 +++++-- pyfakefs/fake_filesystem.py | 6 +++++- tests/fake_os_test.py | 24 ++++++++++++++++-------- 3 files changed, 26 insertions(+), 11 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 51f04e74..e51ddd91 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -8,6 +8,8 @@ The release versions are PyPi releases. #### Infrastructure #### Fixes + * `os.readlink` shall raise under Posix if the argument ends with a path + separator ([#359](../../issues/359)) ## [Version 3.4.1](https://pypi.python.org/pypi/pyfakefs/3.4.1) @@ -39,8 +41,9 @@ must use pyfakefs 3.3 or earlier. start with the message issued in the real file system in Unix systems (see [#202](../../issues/202)) #### Infrastructure - * Changed API to be PEP-8 conform [#186](../../issues/186). Note: The old API is still available. - * Removed Python 2.6 support [#293](../../issues/293) + * Changed API to be PEP-8 conform ([#186](../../issues/186)). Note: The old + API is still available. + * Removed Python 2.6 support ([#293](../../issues/293)) * Added usage documentation to GitHub Pages * Added contributing guide * Added flake8 tests to Travis CI diff --git a/pyfakefs/fake_filesystem.py b/pyfakefs/fake_filesystem.py index 1593a5e2..8c4e54e2 100644 --- a/pyfakefs/fake_filesystem.py +++ b/pyfakefs/fake_filesystem.py @@ -2483,7 +2483,8 @@ def readlink(self, path): Raises: TypeError: if path is None OSError: (with errno=ENOENT) if path is not a valid path, or - (with errno=EINVAL) if path is valid, but is not a symlink. + (with errno=EINVAL) if path is valid, but is not a symlink, + or if the path ends with a path separator (Posix only) """ if path is None: raise TypeError @@ -2493,6 +2494,9 @@ def readlink(self, path): self.raise_os_error(exc.errno, path) if S_IFMT(link_obj.st_mode) != S_IFLNK: self.raise_os_error(errno.EINVAL, path) + if not self.is_windows_fs and path.endswith(self.path_separator): + self.raise_os_error(errno.EINVAL, path) + return link_obj.contents def makedir(self, dir_name, mode=PERM_DEF): diff --git a/tests/fake_os_test.py b/tests/fake_os_test.py index dae4b4aa..2070448b 100644 --- a/tests/fake_os_test.py +++ b/tests/fake_os_test.py @@ -55,14 +55,6 @@ def setUp(self): self.rwx = self.os.R_OK | self.os.W_OK | self.os.X_OK self.rw = self.os.R_OK | self.os.W_OK - def test_359(self): - component1 = "" - path0 = self.make_path('alpha') - self.os.symlink(self.base_path, path0) - path0 = self.os.path.join(path0, component1) - result = self.os.readlink(path0) - print(result) - def test_chdir(self): """chdir should work on a directory.""" directory = self.make_path('foo') @@ -349,6 +341,22 @@ def test_lstat_trailing_sep(self): self.assertEqual(stat, self.os.lstat( self.base_path + self.path_separator() + self.path_separator())) + def test_link_ending_with_sep_posix(self): + # regression test for #359 + self.check_posix_only() + link_path = self.make_path('foo') + self.os.symlink(self.base_path, link_path) + self.assert_raises_os_error(errno.EINVAL, + self.os.readlink, link_path + self.os.sep) + + def test_link_ending_with_sep_windows(self): + self.check_windows_only() + self.skip_if_symlink_not_supported() + link_path = self.make_path('foo') + self.os.symlink(self.base_path, link_path) + self.assertEqual(self.base_path, + self.os.readlink(link_path + self.os.sep)) + @unittest.skipIf(sys.version_info < (3, 3), 'file descriptor as path new in Python 3.3') def test_lstat_uses_open_fd_as_path(self):