python / python/cpython

Result of os.path.realpath("") is incorrect if cwd is on letter-less drive (\\?\-prefixed)

Open
#94,696 3 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

OS-windows stdlib type-bug
Dominant language
Python
Stars
77.2k
Forks
36k
PR merge metrics
PR metrics pending

Description

Bug report

  1. Create volume, dir on it, don't assign a drive letter
  2. In Python:
>>> import os
>>> os.chdir("\\\\?\\Volume{<uuid>}\\<dir>")
>>> os.path.realpath("")
'\\\\?\\Volume{<uuid>}\\<dir>\\.'

The dot is invalid in \\?\-prefixed path.
Dots (. and ..) are normalized by Windows API (at least on NTFS). But \\?\ paths bypass normalization and so may not contain dots. See, for example, here.
All later WinAPI calls with this path fail.

As a simple test, dir \\?\Volume{<uuid>}\dir\. doesn't work whereas dir \\?\Volume{<uuid>}\dir works.

P.S. os.path.realpath(".") gives the same invalid result

Your environment

CPython 3.10.0
Windows 10

Context
The problem arises from pip.
sys.path contains empty string (meaning current dir I presume).
And legacy installation method resolves sys.path relatively to cwd.

Investigation
Here:
https://github.com/python/cpython/blob/4bed0db7c222f8df1b4e31107c0305214caf3f56/Lib/ntpath.py#L704
os.path.join still adds slash even if the second argument is empty. And if the path is ended with slash, dot is added somewhere below.

I fixed it to:

path = cwd if path == "." or path == "" else join(cwd, path)

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start in Lib/ntpath.py around the referenced line 704 and reproduce the Windows behavior with a \?-prefixed volume path whose current directory has no drive letter. Check how os.path.realpath("") and os.path.realpath(".") construct their paths, then add regression coverage showing that neither result ends with an invalid \. component and that the resulting path works with later WinAPI calls.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
operating-systems
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.