@@ -626,12 +626,23 @@ def _getfinalpathname_nonstrict(path, ignored_error=OSError):
626626 allowed_winerror = 1 , 2 , 3 , 5 , 21 , 32 , 50 , 53 , 65 , 67 , 87 , 123 , 161 , 1005 , 1920 , 1921
627627
628628 # Non-strict algorithm is to find as much of the target directory
629- # as we can and join the rest.
629+ # as we can and join the rest. join() is not used, because the tail
630+ # can contain a colon and be mistaken for a drive (gh-102475).
631+ if isinstance (path , bytes ):
632+ sep = b'\\ '
633+ else :
634+ sep = '\\ '
635+
636+ def join (path , tail ):
637+ if path [- 1 :] == sep or not tail :
638+ return path + tail
639+ return path + sep + tail
640+
630641 tail = path [:0 ]
631642 while path :
632643 try :
633644 path = _getfinalpathname (path )
634- return join (path , tail ) if tail else path
645+ return join (path , tail )
635646 except ignored_error as ex :
636647 if ex .winerror not in allowed_winerror :
637648 raise
@@ -642,7 +653,7 @@ def _getfinalpathname_nonstrict(path, ignored_error=OSError):
642653 new_path = _readlink_deep (path ,
643654 ignored_error = ignored_error )
644655 if new_path != path :
645- return join (new_path , tail ) if tail else new_path
656+ return join (new_path , tail )
646657 except ignored_error :
647658 # If we fail to readlink(), let's keep traversing
648659 pass
@@ -657,7 +668,7 @@ def _getfinalpathname_nonstrict(path, ignored_error=OSError):
657668 path , name = split (path )
658669 if path and not name :
659670 return path + tail
660- tail = join (name , tail ) if tail else name
671+ tail = join (name , tail )
661672 return tail
662673
663674 def realpath (path , / , * , strict = False ):
@@ -667,7 +678,6 @@ def realpath(path, /, *, strict=False):
667678 unc_prefix = b'\\ \\ ?\\ UNC\\ '
668679 new_unc_prefix = b'\\ \\ '
669680 colon_sep = b':\\ '
670- cwd = os .getcwdb ()
671681 # bpo-38081: Special case for realpath(b'nul')
672682 devnull = b'nul'
673683 if normcase (path ) == devnull :
@@ -677,7 +687,6 @@ def realpath(path, /, *, strict=False):
677687 unc_prefix = '\\ \\ ?\\ UNC\\ '
678688 new_unc_prefix = '\\ \\ '
679689 colon_sep = ':\\ '
680- cwd = os .getcwd ()
681690 # bpo-38081: Special case for realpath('nul')
682691 devnull = 'nul'
683692 if normcase (path ) == devnull :
@@ -694,7 +703,9 @@ def realpath(path, /, *, strict=False):
694703 ignored_error = OSError
695704
696705 if not had_prefix and not isabs (path ):
697- path = join (cwd , path )
706+ # abspath() is used instead of join(cwd, path), because the path
707+ # can be relative to another drive (gh-102475).
708+ path = abspath (path )
698709 try :
699710 path = _getfinalpathname (path )
700711 initial_winerror = 0
0 commit comments