Skip to content

Commit c91bc27

Browse files
zoobagpshead
authored andcommitted
pythongh-106242: Make ntpath.realpath errors consistent with abspath when there are embedded nulls (pythonGH-108248)
* pythongh-106242: Make ntpath.realpath errors consistent with abspath when there are embedded nulls * Update 2023-08-22-00-36-57.gh-issue-106242.q24ITw.rst mention Windows and the former incorrect ValueError. --------- (cherry picked from commit de33b5c) Co-authored-by: Steve Dower <[email protected]> Co-authored-by: Gregory P. Smith <[email protected]>
1 parent 47f60c3 commit c91bc27

File tree

3 files changed

+22
-0
lines changed

3 files changed

+22
-0
lines changed

Lib/ntpath.py

+12
Original file line numberDiff line numberDiff line change
@@ -721,6 +721,14 @@ def realpath(path, *, strict=False):
721721
try:
722722
path = _getfinalpathname(path)
723723
initial_winerror = 0
724+
except ValueError as ex:
725+
# gh-106242: Raised for embedded null characters
726+
# In strict mode, we convert into an OSError.
727+
# Non-strict mode returns the path as-is, since we've already
728+
# made it absolute.
729+
if strict:
730+
raise OSError(str(ex)) from None
731+
path = normpath(path)
724732
except OSError as ex:
725733
if strict:
726734
raise
@@ -740,6 +748,10 @@ def realpath(path, *, strict=False):
740748
try:
741749
if _getfinalpathname(spath) == path:
742750
path = spath
751+
except ValueError as ex:
752+
# Unexpected, as an invalid path should not have gained a prefix
753+
# at any point, but we ignore this error just in case.
754+
pass
743755
except OSError as ex:
744756
# If the path does not exist and originally did not exist, then
745757
# strip the prefix anyway.

Lib/test/test_ntpath.py

+6
Original file line numberDiff line numberDiff line change
@@ -394,6 +394,10 @@ def test_realpath_basic(self):
394394
d = drives.pop().encode()
395395
self.assertEqual(ntpath.realpath(d), d)
396396

397+
# gh-106242: Embedded nulls and non-strict fallback to abspath
398+
self.assertEqual(ABSTFN + "\0spam",
399+
ntpath.realpath(os_helper.TESTFN + "\0spam", strict=False))
400+
397401
@os_helper.skip_unless_symlink
398402
@unittest.skipUnless(HAVE_GETFINALPATHNAME, 'need _getfinalpathname')
399403
def test_realpath_strict(self):
@@ -404,6 +408,8 @@ def test_realpath_strict(self):
404408
self.addCleanup(os_helper.unlink, ABSTFN)
405409
self.assertRaises(FileNotFoundError, ntpath.realpath, ABSTFN, strict=True)
406410
self.assertRaises(FileNotFoundError, ntpath.realpath, ABSTFN + "2", strict=True)
411+
# gh-106242: Embedded nulls should raise OSError (not ValueError)
412+
self.assertRaises(OSError, ntpath.realpath, ABSTFN + "\0spam", strict=True)
407413

408414
@os_helper.skip_unless_symlink
409415
@unittest.skipUnless(HAVE_GETFINALPATHNAME, 'need _getfinalpathname')
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
Fixes :func:`~os.path.realpath` to behave consistently when passed a path
2+
containing an embedded null character on Windows. In strict mode, it now
3+
raises :exc:`OSError` instead of the unexpected :exc:`ValueError`, and in
4+
non-strict mode will make the path absolute.

0 commit comments

Comments
 (0)