@@ -405,114 +405,121 @@ def _read_directory(archive):
405
405
raise ZipImportError (f"can't open Zip file: { archive !r} " , path = archive )
406
406
407
407
with fp :
408
+ # GH-87235: On macOS all file descriptors for /dev/fd/N share the same
409
+ # file offset, reset the file offset after scanning the zipfile diretory
410
+ # to not cause problems when some runs 'python3 /dev/fd/9 9<some_script'
411
+ start_offset = fp .tell ()
408
412
try :
409
- fp .seek (- END_CENTRAL_DIR_SIZE , 2 )
410
- header_position = fp .tell ()
411
- buffer = fp .read (END_CENTRAL_DIR_SIZE )
412
- except OSError :
413
- raise ZipImportError (f"can't read Zip file: { archive !r} " , path = archive )
414
- if len (buffer ) != END_CENTRAL_DIR_SIZE :
415
- raise ZipImportError (f"can't read Zip file: { archive !r} " , path = archive )
416
- if buffer [:4 ] != STRING_END_ARCHIVE :
417
- # Bad: End of Central Dir signature
418
- # Check if there's a comment.
419
413
try :
420
- fp .seek (0 , 2 )
421
- file_size = fp .tell ()
422
- except OSError :
423
- raise ZipImportError (f"can't read Zip file: { archive !r} " ,
424
- path = archive )
425
- max_comment_start = max (file_size - MAX_COMMENT_LEN -
426
- END_CENTRAL_DIR_SIZE , 0 )
427
- try :
428
- fp .seek (max_comment_start )
429
- data = fp .read ()
430
- except OSError :
431
- raise ZipImportError (f"can't read Zip file: { archive !r} " ,
432
- path = archive )
433
- pos = data .rfind (STRING_END_ARCHIVE )
434
- if pos < 0 :
435
- raise ZipImportError (f'not a Zip file: { archive !r} ' ,
436
- path = archive )
437
- buffer = data [pos :pos + END_CENTRAL_DIR_SIZE ]
438
- if len (buffer ) != END_CENTRAL_DIR_SIZE :
439
- raise ZipImportError (f"corrupt Zip file: { archive !r} " ,
440
- path = archive )
441
- header_position = file_size - len (data ) + pos
442
-
443
- header_size = _unpack_uint32 (buffer [12 :16 ])
444
- header_offset = _unpack_uint32 (buffer [16 :20 ])
445
- if header_position < header_size :
446
- raise ZipImportError (f'bad central directory size: { archive !r} ' , path = archive )
447
- if header_position < header_offset :
448
- raise ZipImportError (f'bad central directory offset: { archive !r} ' , path = archive )
449
- header_position -= header_size
450
- arc_offset = header_position - header_offset
451
- if arc_offset < 0 :
452
- raise ZipImportError (f'bad central directory size or offset: { archive !r} ' , path = archive )
453
-
454
- files = {}
455
- # Start of Central Directory
456
- count = 0
457
- try :
458
- fp .seek (header_position )
459
- except OSError :
460
- raise ZipImportError (f"can't read Zip file: { archive !r} " , path = archive )
461
- while True :
462
- buffer = fp .read (46 )
463
- if len (buffer ) < 4 :
464
- raise EOFError ('EOF read where not expected' )
465
- # Start of file header
466
- if buffer [:4 ] != b'PK\x01 \x02 ' :
467
- break # Bad: Central Dir File Header
468
- if len (buffer ) != 46 :
469
- raise EOFError ('EOF read where not expected' )
470
- flags = _unpack_uint16 (buffer [8 :10 ])
471
- compress = _unpack_uint16 (buffer [10 :12 ])
472
- time = _unpack_uint16 (buffer [12 :14 ])
473
- date = _unpack_uint16 (buffer [14 :16 ])
474
- crc = _unpack_uint32 (buffer [16 :20 ])
475
- data_size = _unpack_uint32 (buffer [20 :24 ])
476
- file_size = _unpack_uint32 (buffer [24 :28 ])
477
- name_size = _unpack_uint16 (buffer [28 :30 ])
478
- extra_size = _unpack_uint16 (buffer [30 :32 ])
479
- comment_size = _unpack_uint16 (buffer [32 :34 ])
480
- file_offset = _unpack_uint32 (buffer [42 :46 ])
481
- header_size = name_size + extra_size + comment_size
482
- if file_offset > header_offset :
483
- raise ZipImportError (f'bad local header offset: { archive !r} ' , path = archive )
484
- file_offset += arc_offset
485
-
486
- try :
487
- name = fp .read (name_size )
414
+ fp .seek (- END_CENTRAL_DIR_SIZE , 2 )
415
+ header_position = fp .tell ()
416
+ buffer = fp .read (END_CENTRAL_DIR_SIZE )
488
417
except OSError :
489
418
raise ZipImportError (f"can't read Zip file: { archive !r} " , path = archive )
490
- if len (name ) != name_size :
419
+ if len (buffer ) != END_CENTRAL_DIR_SIZE :
491
420
raise ZipImportError (f"can't read Zip file: { archive !r} " , path = archive )
492
- # On Windows, calling fseek to skip over the fields we don't use is
493
- # slower than reading the data because fseek flushes stdio's
494
- # internal buffers. See issue #8745.
421
+ if buffer [:4 ] != STRING_END_ARCHIVE :
422
+ # Bad: End of Central Dir signature
423
+ # Check if there's a comment.
424
+ try :
425
+ fp .seek (0 , 2 )
426
+ file_size = fp .tell ()
427
+ except OSError :
428
+ raise ZipImportError (f"can't read Zip file: { archive !r} " ,
429
+ path = archive )
430
+ max_comment_start = max (file_size - MAX_COMMENT_LEN -
431
+ END_CENTRAL_DIR_SIZE , 0 )
432
+ try :
433
+ fp .seek (max_comment_start )
434
+ data = fp .read ()
435
+ except OSError :
436
+ raise ZipImportError (f"can't read Zip file: { archive !r} " ,
437
+ path = archive )
438
+ pos = data .rfind (STRING_END_ARCHIVE )
439
+ if pos < 0 :
440
+ raise ZipImportError (f'not a Zip file: { archive !r} ' ,
441
+ path = archive )
442
+ buffer = data [pos :pos + END_CENTRAL_DIR_SIZE ]
443
+ if len (buffer ) != END_CENTRAL_DIR_SIZE :
444
+ raise ZipImportError (f"corrupt Zip file: { archive !r} " ,
445
+ path = archive )
446
+ header_position = file_size - len (data ) + pos
447
+
448
+ header_size = _unpack_uint32 (buffer [12 :16 ])
449
+ header_offset = _unpack_uint32 (buffer [16 :20 ])
450
+ if header_position < header_size :
451
+ raise ZipImportError (f'bad central directory size: { archive !r} ' , path = archive )
452
+ if header_position < header_offset :
453
+ raise ZipImportError (f'bad central directory offset: { archive !r} ' , path = archive )
454
+ header_position -= header_size
455
+ arc_offset = header_position - header_offset
456
+ if arc_offset < 0 :
457
+ raise ZipImportError (f'bad central directory size or offset: { archive !r} ' , path = archive )
458
+
459
+ files = {}
460
+ # Start of Central Directory
461
+ count = 0
495
462
try :
496
- if len (fp .read (header_size - name_size )) != header_size - name_size :
497
- raise ZipImportError (f"can't read Zip file: { archive !r} " , path = archive )
463
+ fp .seek (header_position )
498
464
except OSError :
499
465
raise ZipImportError (f"can't read Zip file: { archive !r} " , path = archive )
466
+ while True :
467
+ buffer = fp .read (46 )
468
+ if len (buffer ) < 4 :
469
+ raise EOFError ('EOF read where not expected' )
470
+ # Start of file header
471
+ if buffer [:4 ] != b'PK\x01 \x02 ' :
472
+ break # Bad: Central Dir File Header
473
+ if len (buffer ) != 46 :
474
+ raise EOFError ('EOF read where not expected' )
475
+ flags = _unpack_uint16 (buffer [8 :10 ])
476
+ compress = _unpack_uint16 (buffer [10 :12 ])
477
+ time = _unpack_uint16 (buffer [12 :14 ])
478
+ date = _unpack_uint16 (buffer [14 :16 ])
479
+ crc = _unpack_uint32 (buffer [16 :20 ])
480
+ data_size = _unpack_uint32 (buffer [20 :24 ])
481
+ file_size = _unpack_uint32 (buffer [24 :28 ])
482
+ name_size = _unpack_uint16 (buffer [28 :30 ])
483
+ extra_size = _unpack_uint16 (buffer [30 :32 ])
484
+ comment_size = _unpack_uint16 (buffer [32 :34 ])
485
+ file_offset = _unpack_uint32 (buffer [42 :46 ])
486
+ header_size = name_size + extra_size + comment_size
487
+ if file_offset > header_offset :
488
+ raise ZipImportError (f'bad local header offset: { archive !r} ' , path = archive )
489
+ file_offset += arc_offset
500
490
501
- if flags & 0x800 :
502
- # UTF-8 file names extension
503
- name = name .decode ()
504
- else :
505
- # Historical ZIP filename encoding
506
491
try :
507
- name = name .decode ('ascii' )
508
- except UnicodeDecodeError :
509
- name = name .decode ('latin1' ).translate (cp437_table )
510
-
511
- name = name .replace ('/' , path_sep )
512
- path = _bootstrap_external ._path_join (archive , name )
513
- t = (path , compress , data_size , file_size , file_offset , time , date , crc )
514
- files [name ] = t
515
- count += 1
492
+ name = fp .read (name_size )
493
+ except OSError :
494
+ raise ZipImportError (f"can't read Zip file: { archive !r} " , path = archive )
495
+ if len (name ) != name_size :
496
+ raise ZipImportError (f"can't read Zip file: { archive !r} " , path = archive )
497
+ # On Windows, calling fseek to skip over the fields we don't use is
498
+ # slower than reading the data because fseek flushes stdio's
499
+ # internal buffers. See issue #8745.
500
+ try :
501
+ if len (fp .read (header_size - name_size )) != header_size - name_size :
502
+ raise ZipImportError (f"can't read Zip file: { archive !r} " , path = archive )
503
+ except OSError :
504
+ raise ZipImportError (f"can't read Zip file: { archive !r} " , path = archive )
505
+
506
+ if flags & 0x800 :
507
+ # UTF-8 file names extension
508
+ name = name .decode ()
509
+ else :
510
+ # Historical ZIP filename encoding
511
+ try :
512
+ name = name .decode ('ascii' )
513
+ except UnicodeDecodeError :
514
+ name = name .decode ('latin1' ).translate (cp437_table )
515
+
516
+ name = name .replace ('/' , path_sep )
517
+ path = _bootstrap_external ._path_join (archive , name )
518
+ t = (path , compress , data_size , file_size , file_offset , time , date , crc )
519
+ files [name ] = t
520
+ count += 1
521
+ finally :
522
+ fp .seek (start_offset )
516
523
_bootstrap ._verbose_message ('zipimport: found {} names in {!r}' , count , archive )
517
524
return files
518
525
0 commit comments