[issue27403] os.path.dirname doesn't handle Windows' URNs correctly

Eryk Sun report at bugs.python.org
Mon Jun 27 18:08:52 EDT 2016


Eryk Sun added the comment:

dirname() is implemented via split(), which begins by calling splitdrive(). The 'drive' for a UNC path is the r"\\server\share" component. For example:

    >>> path = r'\\server\share\folder\file'
    >>> os.path.splitdrive(path)
    ('\\\\server\\share', '\\folder\\file')
    >>> os.path.split(path)
    ('\\\\server\\share\\folder', 'file')
    >>> os.path.dirname(path)
    '\\\\server\\share\\folder'

If you double the initial slashes, it's no longer a valid UNC path:

    >>> path = r'\\\\server\\share\\folder\\file'
    >>> os.path.splitdrive(path)
    ('', '\\\\\\\\server\\\\share\\\\folder\\\\file')
    >>> os.path.split(path)
    ('\\\\\\\\server\\\\share\\\\folder', 'file')
    >>> os.path.dirname(path)
    '\\\\\\\\server\\\\share\\\\folder'

Windows itself will attempt to handle it as a UNC path, but the path is invalid. Specifically, before passing the path to the kernel, Windows collapses all of the extra slashes, except an initial slash count greater than two always leaves an extra slash in the path. For example:

    >>> open(r'\\\\server\\share\\folder\\file')
    Breakpoint 0 hit
    ntdll!NtCreateFile:
    00007ffb`a1f25b70 4c8bd1          mov     r10,rcx
    0:000> !obja @r8
    Obja +00000049781ef160 at 00000049781ef160:
            Name is \??\UNC\\server\share\folder\file
            OBJ_CASE_INSENSITIVE

Notice the extra backlash in "UNC\\server". Thus a valid UNC path must start with exactly two slashes. 

Using forward slash is generally fine. The Windows API substitutes backslash for slash before passing a path to the kernel. For example:

    >>> open(r'//server/share/folder/file')
    Breakpoint 0 hit
    ntdll!NtCreateFile:
    00007ffb`a1f25b70 4c8bd1          mov     r10,rcx
    0:000> !obja @r8
    Obja +00000049781ef160 at 00000049781ef160:
            Name is \??\UNC\server\share\folder\file
            OBJ_CASE_INSENSITIVE

Except you can't use forward slash with a "\\?\" path, which bypasses normal path processing. For example:

    >>> open(r'\\?\UNC/server/share/folder/file')
    Breakpoint 0 hit
    ntdll!NtCreateFile:
    00007ffb`a1f25b70 4c8bd1          mov     r10,rcx
    0:000> !obja @r8
    Obja +00000049781ef160 at 00000049781ef160:
            Name is \??\UNC/server/share/folder/file
            OBJ_CASE_INSENSITIVE

In the kernel '/' isn't a path separator. It's just another name character, so this (potentially) looks for a server named "/server/share/folder/file". Microsoft file systems forbid using slash in names (for POSIX compatibility and to avoid needless confusion), but you can use slash in the name of kernel objects such as Event objects, or even in the name of DOS devices defined via DefineDosDevice.

----------
nosy: +eryksun
resolution:  -> not a bug
stage:  -> resolved
status: open -> closed

_______________________________________
Python tracker <report at bugs.python.org>
<http://bugs.python.org/issue27403>
_______________________________________


More information about the Python-bugs-list mailing list