Skip to content

Commit 8927cf0

Browse files
miss-islingtonzoobagpshead
authored
[3.11] gh-106242: Make ntpath.realpath errors consistent with abspath when there are embedded nulls (GH-108248)
gh-106242: Make ntpath.realpath errors consistent with abspath when there are embedded nulls (GH-108248) --------- (cherry picked from commit de33b5c) Co-authored-by: Steve Dower <[email protected]> Co-authored-by: Gregory P. Smith <[email protected]>
1 parent d22ac0c commit 8927cf0

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
@@ -695,6 +695,14 @@ def realpath(path, *, strict=False):
695695
try:
696696
path = _getfinalpathname(path)
697697
initial_winerror = 0
698+
except ValueError as ex:
699+
# gh-106242: Raised for embedded null characters
700+
# In strict mode, we convert into an OSError.
701+
# Non-strict mode returns the path as-is, since we've already
702+
# made it absolute.
703+
if strict:
704+
raise OSError(str(ex)) from None
705+
path = normpath(path)
698706
except OSError as ex:
699707
if strict:
700708
raise
@@ -714,6 +722,10 @@ def realpath(path, *, strict=False):
714722
try:
715723
if _getfinalpathname(spath) == path:
716724
path = spath
725+
except ValueError as ex:
726+
# Unexpected, as an invalid path should not have gained a prefix
727+
# at any point, but we ignore this error just in case.
728+
pass
717729
except OSError as ex:
718730
# If the path does not exist and originally did not exist, then
719731
# strip the prefix anyway.

Lib/test/test_ntpath.py

+6
Original file line numberDiff line numberDiff line change
@@ -332,6 +332,10 @@ def test_realpath_basic(self):
332332
raise OSError("No free drive letters available")
333333
self.assertEqual(ntpath.realpath(d), d)
334334

335+
# gh-106242: Embedded nulls and non-strict fallback to abspath
336+
self.assertEqual(ABSTFN + "\0spam",
337+
ntpath.realpath(os_helper.TESTFN + "\0spam", strict=False))
338+
335339
@os_helper.skip_unless_symlink
336340
@unittest.skipUnless(HAVE_GETFINALPATHNAME, 'need _getfinalpathname')
337341
def test_realpath_strict(self):
@@ -342,6 +346,8 @@ def test_realpath_strict(self):
342346
self.addCleanup(os_helper.unlink, ABSTFN)
343347
self.assertRaises(FileNotFoundError, ntpath.realpath, ABSTFN, strict=True)
344348
self.assertRaises(FileNotFoundError, ntpath.realpath, ABSTFN + "2", strict=True)
349+
# gh-106242: Embedded nulls should raise OSError (not ValueError)
350+
self.assertRaises(OSError, ntpath.realpath, ABSTFN + "\0spam", strict=True)
345351

346352
@os_helper.skip_unless_symlink
347353
@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)