From 0c2b0a02a20b65e881421d4fae9654a9b8cad5d3 Mon Sep 17 00:00:00 2001 From: Steve Dower Date: Wed, 21 Aug 2019 14:58:15 -0700 Subject: [PATCH 1/5] bpo-9949: Call normpath first in realpath --- Lib/ntpath.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Lib/ntpath.py b/Lib/ntpath.py index ef4999e1473acb..e8e4ecb39d2a13 100644 --- a/Lib/ntpath.py +++ b/Lib/ntpath.py @@ -458,7 +458,8 @@ def normpath(path): # in the case of paths with these prefixes: # \\.\ -> device names # \\?\ -> literal paths - # do not do any normalization, but return the path unchanged + # do not do any normalization, but return the path + # unchanged apart from the call to os.fspath() return path path = path.replace(altsep, sep) prefix, path = splitdrive(path) @@ -575,7 +576,7 @@ def _getfinalpathname_nonstrict(path): return abspath(tail) def realpath(path): - path = os.fspath(path) + path = normpath(path) if isinstance(path, bytes): prefix = b'\\\\?\\' unc_prefix = b'\\\\?\\UNC\\' From f61a133083c204ae84573c4a9ea6ab7ce2725c7b Mon Sep 17 00:00:00 2001 From: Steve Dower Date: Wed, 21 Aug 2019 15:25:00 -0700 Subject: [PATCH 2/5] Strip prefix when path did not exist at the beginning --- Lib/ntpath.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Lib/ntpath.py b/Lib/ntpath.py index e8e4ecb39d2a13..1d22d5f1dc2ab5 100644 --- a/Lib/ntpath.py +++ b/Lib/ntpath.py @@ -587,6 +587,7 @@ def realpath(path): unc_prefix = '\\\\?\\UNC\\' new_unc_prefix = '\\\\' cwd = os.getcwd() + did_not_exist = not exists(path) had_prefix = path.startswith(prefix) path = _getfinalpathname_nonstrict(path) # The path returned by _getfinalpathname will always start with \\?\ - @@ -604,7 +605,10 @@ def realpath(path): if _getfinalpathname(spath) == path: path = spath except OSError as ex: - pass + # If the path does not exist and originally did not exist, then + # strip the prefix anyway. + if ex.winerror in {2, 3} and did_not_exist: + path = spath return path From 3569826b1379ef4e563c5661f9f3086b2fbda846 Mon Sep 17 00:00:00 2001 From: Steve Dower Date: Wed, 21 Aug 2019 15:41:13 -0700 Subject: [PATCH 3/5] Use lexists() instead of exists(), and fix test --- Lib/ntpath.py | 2 +- Lib/test/test_ntpath.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Lib/ntpath.py b/Lib/ntpath.py index 1d22d5f1dc2ab5..165df44a953038 100644 --- a/Lib/ntpath.py +++ b/Lib/ntpath.py @@ -587,7 +587,7 @@ def realpath(path): unc_prefix = '\\\\?\\UNC\\' new_unc_prefix = '\\\\' cwd = os.getcwd() - did_not_exist = not exists(path) + did_not_exist = not lexists(path) had_prefix = path.startswith(prefix) path = _getfinalpathname_nonstrict(path) # The path returned by _getfinalpathname will always start with \\?\ - diff --git a/Lib/test/test_ntpath.py b/Lib/test/test_ntpath.py index 74dc8c378e2746..22e592b115cf0e 100644 --- a/Lib/test/test_ntpath.py +++ b/Lib/test/test_ntpath.py @@ -333,7 +333,7 @@ def test_realpath_symlink_loops(self): self.assertEqual(ntpath.realpath(ABSTFN + "1\\.."), ntpath.dirname(ABSTFN)) self.assertEqual(ntpath.realpath(ABSTFN + "1\\..\\x"), - ntpath.dirname(P + ABSTFN) + "\\x") + ntpath.dirname(ABSTFN) + "\\x") os.symlink(ABSTFN + "x", ABSTFN + "y") self.assertEqual(ntpath.realpath(ABSTFN + "1\\..\\" + ntpath.basename(ABSTFN) + "y"), From 51b3d600264b6e4c198f9a413a9b026f7285c091 Mon Sep 17 00:00:00 2001 From: Steve Dower Date: Wed, 21 Aug 2019 15:58:54 -0700 Subject: [PATCH 4/5] No, exists was right --- Lib/ntpath.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lib/ntpath.py b/Lib/ntpath.py index 165df44a953038..1d22d5f1dc2ab5 100644 --- a/Lib/ntpath.py +++ b/Lib/ntpath.py @@ -587,7 +587,7 @@ def realpath(path): unc_prefix = '\\\\?\\UNC\\' new_unc_prefix = '\\\\' cwd = os.getcwd() - did_not_exist = not lexists(path) + did_not_exist = not exists(path) had_prefix = path.startswith(prefix) path = _getfinalpathname_nonstrict(path) # The path returned by _getfinalpathname will always start with \\?\ - From f3d9c1e3e2a136385f86f182a4d88ea100d580a1 Mon Sep 17 00:00:00 2001 From: Steve Dower Date: Wed, 21 Aug 2019 16:14:15 -0700 Subject: [PATCH 5/5] Evil symlink loops --- Lib/test/test_ntpath.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lib/test/test_ntpath.py b/Lib/test/test_ntpath.py index 22e592b115cf0e..285fb69dc1e88f 100644 --- a/Lib/test/test_ntpath.py +++ b/Lib/test/test_ntpath.py @@ -337,7 +337,7 @@ def test_realpath_symlink_loops(self): os.symlink(ABSTFN + "x", ABSTFN + "y") self.assertEqual(ntpath.realpath(ABSTFN + "1\\..\\" + ntpath.basename(ABSTFN) + "y"), - P + ABSTFN + "x") + ABSTFN + "x") self.assertIn(ntpath.realpath(ABSTFN + "1\\..\\" + ntpath.basename(ABSTFN) + "1"), expected)