@@ -124,6 +124,22 @@ def test_splitdrive(self):
124124        tester ('ntpath.splitdrive("//?/UNC/server/share/dir")' ,
125125               ("//?/UNC/server/share" , "/dir" ))
126126
127+     def  test_splitdrive_invalid_paths (self ):
128+         splitdrive  =  ntpath .splitdrive 
129+         self .assertEqual (splitdrive ('\\ \\ ser\x00 ver\\ sha\x00 re\\ di\x00 r' ),
130+                          ('\\ \\ ser\x00 ver\\ sha\x00 re' , '\\ di\x00 r' ))
131+         self .assertEqual (splitdrive (b'\\ \\ ser\x00 ver\\ sha\x00 re\\ di\x00 r' ),
132+                          (b'\\ \\ ser\x00 ver\\ sha\x00 re' , b'\\ di\x00 r' ))
133+         self .assertEqual (splitdrive ("\\ \\ \udfff \\ \udffe \\ \udffd " ),
134+                          ('\\ \\ \udfff \\ \udffe ' , '\\ \udffd ' ))
135+         if  sys .platform  ==  'win32' :
136+             self .assertRaises (UnicodeDecodeError , splitdrive , b'\\ \\ \xff \\ share\\ dir' )
137+             self .assertRaises (UnicodeDecodeError , splitdrive , b'\\ \\ server\\ \xff \\ dir' )
138+             self .assertRaises (UnicodeDecodeError , splitdrive , b'\\ \\ server\\ share\\ \xff ' )
139+         else :
140+             self .assertEqual (splitdrive (b'\\ \\ \xff \\ \xfe \\ \xfd ' ),
141+                              (b'\\ \\ \xff \\ \xfe ' , b'\\ \xfd ' ))
142+ 
127143    def  test_splitroot (self ):
128144        tester ("ntpath.splitroot('')" , ('' , '' , '' ))
129145        tester ("ntpath.splitroot('foo')" , ('' , '' , 'foo' ))
@@ -214,6 +230,22 @@ def test_splitroot(self):
214230        tester ('ntpath.splitroot(" :/foo")' , (" :" , "/" , "foo" ))
215231        tester ('ntpath.splitroot("/:/foo")' , ("" , "/" , ":/foo" ))
216232
233+     def  test_splitroot_invalid_paths (self ):
234+         splitroot  =  ntpath .splitroot 
235+         self .assertEqual (splitroot ('\\ \\ ser\x00 ver\\ sha\x00 re\\ di\x00 r' ),
236+                          ('\\ \\ ser\x00 ver\\ sha\x00 re' , '\\ ' , 'di\x00 r' ))
237+         self .assertEqual (splitroot (b'\\ \\ ser\x00 ver\\ sha\x00 re\\ di\x00 r' ),
238+                          (b'\\ \\ ser\x00 ver\\ sha\x00 re' , b'\\ ' , b'di\x00 r' ))
239+         self .assertEqual (splitroot ("\\ \\ \udfff \\ \udffe \\ \udffd " ),
240+                          ('\\ \\ \udfff \\ \udffe ' , '\\ ' , '\udffd ' ))
241+         if  sys .platform  ==  'win32' :
242+             self .assertRaises (UnicodeDecodeError , splitroot , b'\\ \\ \xff \\ share\\ dir' )
243+             self .assertRaises (UnicodeDecodeError , splitroot , b'\\ \\ server\\ \xff \\ dir' )
244+             self .assertRaises (UnicodeDecodeError , splitroot , b'\\ \\ server\\ share\\ \xff ' )
245+         else :
246+             self .assertEqual (splitroot (b'\\ \\ \xff \\ \xfe \\ \xfd ' ),
247+                              (b'\\ \\ \xff \\ \xfe ' , b'\\ ' , b'\xfd ' ))
248+ 
217249    def  test_split (self ):
218250        tester ('ntpath.split("c:\\ foo\\ bar")' , ('c:\\ foo' , 'bar' ))
219251        tester ('ntpath.split("\\ \\ conky\\ mountpoint\\ foo\\ bar")' ,
@@ -226,6 +258,21 @@ def test_split(self):
226258        tester ('ntpath.split("c:/")' , ('c:/' , '' ))
227259        tester ('ntpath.split("//conky/mountpoint/")' , ('//conky/mountpoint/' , '' ))
228260
261+     def  test_split_invalid_paths (self ):
262+         split  =  ntpath .split 
263+         self .assertEqual (split ('c:\\ fo\x00 o\\ ba\x00 r' ),
264+                          ('c:\\ fo\x00 o' , 'ba\x00 r' ))
265+         self .assertEqual (split (b'c:\\ fo\x00 o\\ ba\x00 r' ),
266+                          (b'c:\\ fo\x00 o' , b'ba\x00 r' ))
267+         self .assertEqual (split ('c:\\ \udfff \\ \udffe ' ),
268+                          ('c:\\ \udfff ' , '\udffe ' ))
269+         if  sys .platform  ==  'win32' :
270+             self .assertRaises (UnicodeDecodeError , split , b'c:\\ \xff \\ bar' )
271+             self .assertRaises (UnicodeDecodeError , split , b'c:\\ foo\\ \xff ' )
272+         else :
273+             self .assertEqual (split (b'c:\\ \xff \\ \xfe ' ),
274+                              (b'c:\\ \xff ' , b'\xfe ' ))
275+ 
229276    def  test_isabs (self ):
230277        tester ('ntpath.isabs("foo\\ bar")' , 0 )
231278        tester ('ntpath.isabs("foo/bar")' , 0 )
@@ -333,6 +380,30 @@ def test_join(self):
333380        tester ("ntpath.join('D:a', './c:b')" , 'D:a\\ .\\ c:b' )
334381        tester ("ntpath.join('D:/a', './c:b')" , 'D:\\ a\\ .\\ c:b' )
335382
383+     def  test_normcase (self ):
384+         normcase  =  ntpath .normcase 
385+         self .assertEqual (normcase ('' ), '' )
386+         self .assertEqual (normcase (b'' ), b'' )
387+         self .assertEqual (normcase ('ABC' ), 'abc' )
388+         self .assertEqual (normcase (b'ABC' ), b'abc' )
389+         self .assertEqual (normcase ('\xc4 \u0141 \u03a8 ' ), '\xe4 \u0142 \u03c8 ' )
390+         expected  =  '\u03c9 \u2126 '  if  sys .platform  ==  'win32'  else  '\u03c9 \u03c9 ' 
391+         self .assertEqual (normcase ('\u03a9 \u2126 ' ), expected )
392+         if  sys .platform  ==  'win32'  or  sys .getfilesystemencoding () ==  'utf-8' :
393+             self .assertEqual (normcase ('\xc4 \u0141 \u03a8 ' .encode ()),
394+                              '\xe4 \u0142 \u03c8 ' .encode ())
395+             self .assertEqual (normcase ('\u03a9 \u2126 ' .encode ()),
396+                              expected .encode ())
397+ 
398+     def  test_normcase_invalid_paths (self ):
399+         normcase  =  ntpath .normcase 
400+         self .assertEqual (normcase ('abc\x00 def' ), 'abc\x00 def' )
401+         self .assertEqual (normcase (b'abc\x00 def' ), b'abc\x00 def' )
402+         self .assertEqual (normcase ('\udfff ' ), '\udfff ' )
403+         if  sys .platform  ==  'win32' :
404+             path  =  b'ABC'  +  bytes (range (128 , 256 ))
405+             self .assertEqual (normcase (path ), path .lower ())
406+ 
336407    def  test_normpath (self ):
337408        tester ("ntpath.normpath('A//////././//.//B')" , r'A\B' )
338409        tester ("ntpath.normpath('A/./B')" , r'A\B' )
@@ -381,6 +452,21 @@ def test_normpath(self):
381452        tester ("ntpath.normpath('\\ \\ ')" , '\\ \\ ' )
382453        tester ("ntpath.normpath('//?/UNC/server/share/..')" , '\\ \\ ?\\ UNC\\ server\\ share\\ ' )
383454
455+     def  test_normpath_invalid_paths (self ):
456+         normpath  =  ntpath .normpath 
457+         self .assertEqual (normpath ('fo\x00 o' ), 'fo\x00 o' )
458+         self .assertEqual (normpath (b'fo\x00 o' ), b'fo\x00 o' )
459+         self .assertEqual (normpath ('fo\x00 o\\ ..\\ bar' ), 'bar' )
460+         self .assertEqual (normpath (b'fo\x00 o\\ ..\\ bar' ), b'bar' )
461+         self .assertEqual (normpath ('\udfff ' ), '\udfff ' )
462+         self .assertEqual (normpath ('\udfff \\ ..\\ foo' ), 'foo' )
463+         if  sys .platform  ==  'win32' :
464+             self .assertRaises (UnicodeDecodeError , normpath , b'\xff ' )
465+             self .assertRaises (UnicodeDecodeError , normpath , b'\xff \\ ..\\ foo' )
466+         else :
467+             self .assertEqual (normpath (b'\xff ' ), b'\xff ' )
468+             self .assertEqual (normpath (b'\xff \\ ..\\ foo' ), b'foo' )
469+ 
384470    def  test_realpath_curdir (self ):
385471        expected  =  ntpath .normpath (os .getcwd ())
386472        tester ("ntpath.realpath('.')" , expected )
@@ -420,10 +506,6 @@ def test_realpath_basic(self):
420506        d  =  drives .pop ().encode ()
421507        self .assertEqual (ntpath .realpath (d ), d )
422508
423-         # gh-106242: Embedded nulls and non-strict fallback to abspath 
424-         self .assertEqual (ABSTFN  +  "\0 spam" ,
425-                          ntpath .realpath (os_helper .TESTFN  +  "\0 spam" , strict = False ))
426- 
427509    @os_helper .skip_unless_symlink  
428510    @unittest .skipUnless (HAVE_GETFINALPATHNAME , 'need _getfinalpathname' ) 
429511    def  test_realpath_strict (self ):
@@ -434,8 +516,51 @@ def test_realpath_strict(self):
434516        self .addCleanup (os_helper .unlink , ABSTFN )
435517        self .assertRaises (FileNotFoundError , ntpath .realpath , ABSTFN , strict = True )
436518        self .assertRaises (FileNotFoundError , ntpath .realpath , ABSTFN  +  "2" , strict = True )
519+ 
520+     @unittest .skipUnless (HAVE_GETFINALPATHNAME , 'need _getfinalpathname' ) 
521+     def  test_realpath_invalid_paths (self ):
522+         realpath  =  ntpath .realpath 
523+         ABSTFN  =  ntpath .abspath (os_helper .TESTFN )
524+         ABSTFNb  =  os .fsencode (ABSTFN )
525+         path  =  ABSTFN  +  '\x00 ' 
526+         # gh-106242: Embedded nulls and non-strict fallback to abspath 
527+         self .assertEqual (realpath (path , strict = False ), path )
437528        # gh-106242: Embedded nulls should raise OSError (not ValueError) 
438-         self .assertRaises (OSError , ntpath .realpath , ABSTFN  +  "\0 spam" , strict = True )
529+         self .assertRaises (OSError , realpath , path , strict = True )
530+         path  =  ABSTFNb  +  b'\x00 ' 
531+         self .assertEqual (realpath (path , strict = False ), path )
532+         self .assertRaises (OSError , realpath , path , strict = True )
533+         path  =  ABSTFN  +  '\\ nonexistent\\ x\x00 ' 
534+         self .assertEqual (realpath (path , strict = False ), path )
535+         self .assertRaises (OSError , realpath , path , strict = True )
536+         path  =  ABSTFNb  +  b'\\ nonexistent\\ x\x00 ' 
537+         self .assertEqual (realpath (path , strict = False ), path )
538+         self .assertRaises (OSError , realpath , path , strict = True )
539+         path  =  ABSTFN  +  '\x00 \\ ..' 
540+         self .assertEqual (realpath (path , strict = False ), os .getcwd ())
541+         self .assertEqual (realpath (path , strict = True ), os .getcwd ())
542+         path  =  ABSTFNb  +  b'\x00 \\ ..' 
543+         self .assertEqual (realpath (path , strict = False ), os .getcwdb ())
544+         self .assertEqual (realpath (path , strict = True ), os .getcwdb ())
545+         path  =  ABSTFN  +  '\\ nonexistent\\ x\x00 \\ ..' 
546+         self .assertEqual (realpath (path , strict = False ), ABSTFN  +  '\\ nonexistent' )
547+         self .assertRaises (OSError , realpath , path , strict = True )
548+         path  =  ABSTFNb  +  b'\\ nonexistent\\ x\x00 \\ ..' 
549+         self .assertEqual (realpath (path , strict = False ), ABSTFNb  +  b'\\ nonexistent' )
550+         self .assertRaises (OSError , realpath , path , strict = True )
551+ 
552+         path  =  ABSTFNb  +  b'\xff ' 
553+         self .assertRaises (UnicodeDecodeError , realpath , path , strict = False )
554+         self .assertRaises (UnicodeDecodeError , realpath , path , strict = True )
555+         path  =  ABSTFNb  +  b'\\ nonexistent\\ \xff ' 
556+         self .assertRaises (UnicodeDecodeError , realpath , path , strict = False )
557+         self .assertRaises (UnicodeDecodeError , realpath , path , strict = True )
558+         path  =  ABSTFNb  +  b'\xff \\ ..' 
559+         self .assertRaises (UnicodeDecodeError , realpath , path , strict = False )
560+         self .assertRaises (UnicodeDecodeError , realpath , path , strict = True )
561+         path  =  ABSTFNb  +  b'\\ nonexistent\\ \xff \\ ..' 
562+         self .assertRaises (UnicodeDecodeError , realpath , path , strict = False )
563+         self .assertRaises (UnicodeDecodeError , realpath , path , strict = True )
439564
440565    @os_helper .skip_unless_symlink  
441566    @unittest .skipUnless (HAVE_GETFINALPATHNAME , 'need _getfinalpathname' ) 
@@ -812,8 +937,6 @@ def test_abspath(self):
812937        tester ('ntpath.abspath("C:/nul")' ,  "\\ \\ .\\ nul" )
813938        tester ('ntpath.abspath("C:\\ nul")' , "\\ \\ .\\ nul" )
814939        self .assertTrue (ntpath .isabs (ntpath .abspath ("C:spam" )))
815-         self .assertEqual (ntpath .abspath ("C:\x00 " ), ntpath .join (ntpath .abspath ("C:" ), "\x00 " ))
816-         self .assertEqual (ntpath .abspath ("\x00 :spam" ), "\x00 :\\ spam" )
817940        tester ('ntpath.abspath("//..")' ,           "\\ \\ " )
818941        tester ('ntpath.abspath("//../")' ,          "\\ \\ ..\\ " )
819942        tester ('ntpath.abspath("//../..")' ,        "\\ \\ ..\\ " )
@@ -847,6 +970,26 @@ def test_abspath(self):
847970            drive , _  =  ntpath .splitdrive (cwd_dir )
848971            tester ('ntpath.abspath("/abc/")' , drive  +  "\\ abc" )
849972
973+     def  test_abspath_invalid_paths (self ):
974+         abspath  =  ntpath .abspath 
975+         if  sys .platform  ==  'win32' :
976+             self .assertEqual (abspath ("C:\x00 " ), ntpath .join (abspath ("C:" ), "\x00 " ))
977+             self .assertEqual (abspath (b"C:\x00 " ), ntpath .join (abspath (b"C:" ), b"\x00 " ))
978+             self .assertEqual (abspath ("\x00 :spam" ), "\x00 :\\ spam" )
979+             self .assertEqual (abspath (b"\x00 :spam" ), b"\x00 :\\ spam" )
980+         self .assertEqual (abspath ('c:\\ fo\x00 o' ), 'c:\\ fo\x00 o' )
981+         self .assertEqual (abspath (b'c:\\ fo\x00 o' ), b'c:\\ fo\x00 o' )
982+         self .assertEqual (abspath ('c:\\ fo\x00 o\\ ..\\ bar' ), 'c:\\ bar' )
983+         self .assertEqual (abspath (b'c:\\ fo\x00 o\\ ..\\ bar' ), b'c:\\ bar' )
984+         self .assertEqual (abspath ('c:\\ \udfff ' ), 'c:\\ \udfff ' )
985+         self .assertEqual (abspath ('c:\\ \udfff \\ ..\\ foo' ), 'c:\\ foo' )
986+         if  sys .platform  ==  'win32' :
987+             self .assertRaises (UnicodeDecodeError , abspath , b'c:\\ \xff ' )
988+             self .assertRaises (UnicodeDecodeError , abspath , b'c:\\ \xff \\ ..\\ foo' )
989+         else :
990+             self .assertEqual (abspath (b'c:\\ \xff ' ), b'c:\\ \xff ' )
991+             self .assertEqual (abspath (b'c:\\ \xff \\ ..\\ foo' ), b'c:\\ foo' )
992+ 
850993    def  test_relpath (self ):
851994        tester ('ntpath.relpath("a")' , 'a' )
852995        tester ('ntpath.relpath(ntpath.abspath("a"))' , 'a' )
@@ -990,6 +1133,18 @@ def test_ismount(self):
9901133            self .assertTrue (ntpath .ismount (b"\\ \\ localhost\\ c$" ))
9911134            self .assertTrue (ntpath .ismount (b"\\ \\ localhost\\ c$\\ " ))
9921135
1136+     def  test_ismount_invalid_paths (self ):
1137+         ismount  =  ntpath .ismount 
1138+         self .assertFalse (ismount ("c:\\ \udfff " ))
1139+         if  sys .platform  ==  'win32' :
1140+             self .assertRaises (ValueError , ismount , "c:\\ \x00 " )
1141+             self .assertRaises (ValueError , ismount , b"c:\\ \x00 " )
1142+             self .assertRaises (UnicodeDecodeError , ismount , b"c:\\ \xff " )
1143+         else :
1144+             self .assertFalse (ismount ("c:\\ \x00 " ))
1145+             self .assertFalse (ismount (b"c:\\ \x00 " ))
1146+             self .assertFalse (ismount (b"c:\\ \xff " ))
1147+ 
9931148    def  test_isreserved (self ):
9941149        self .assertFalse (ntpath .isreserved ('' ))
9951150        self .assertFalse (ntpath .isreserved ('.' ))
@@ -1096,6 +1251,13 @@ def test_isjunction(self):
10961251                self .assertFalse (ntpath .isjunction ('tmpdir' ))
10971252                self .assertPathEqual (ntpath .realpath ('testjunc' ), ntpath .realpath ('tmpdir' ))
10981253
1254+     def  test_isfile_invalid_paths (self ):
1255+         isfile  =  ntpath .isfile 
1256+         self .assertIs (isfile ('/tmp\udfff abcds' ), False )
1257+         self .assertIs (isfile (b'/tmp\xff abcds' ), False )
1258+         self .assertIs (isfile ('/tmp\x00 abcds' ), False )
1259+         self .assertIs (isfile (b'/tmp\x00 abcds' ), False )
1260+ 
10991261    @unittest .skipIf (sys .platform  !=  'win32' , "drive letters are a windows concept" ) 
11001262    def  test_isfile_driveletter (self ):
11011263        drive  =  os .environ .get ('SystemDrive' )
@@ -1196,9 +1358,6 @@ def _check_function(self, func):
11961358
11971359    def  test_path_normcase (self ):
11981360        self ._check_function (self .path .normcase )
1199-         if  sys .platform  ==  'win32' :
1200-             self .assertEqual (ntpath .normcase ('\u03a9 \u2126 ' ), 'ωΩ' )
1201-             self .assertEqual (ntpath .normcase ('abc\x00 def' ), 'abc\x00 def' )
12021361
12031362    def  test_path_isabs (self ):
12041363        self ._check_function (self .path .isabs )
0 commit comments