@@ -102,16 +102,17 @@ static bool hasZip64Info(const char* extraFieldPtr, size_t extraFieldLength)
102102 * Reads a 64-bit field from @p offsetTrusted (does not include the 4-byte
103103 * header).
104104 *
105- * @p offsetTrusted An offset to read from that is guaranteed to be <= 20 .
105+ * @p offsetTrusted An offset to read from that is guaranteed to be <= 16 .
106106 */
107107static ZL_RESULT_OF (uint64_t ) readZip64Info (
108+ ZL_OperationContext * opCtx ,
108109 const char * zip64InfoPtr ,
109110 size_t zip64InfoSize ,
110111 size_t offsetTrusted )
111112{
112- ZL_RESULT_DECLARE_SCOPE (uint64_t , NULL );
113+ ZL_RESULT_DECLARE_SCOPE (uint64_t , opCtx );
113114 const char * const zip64InfoEnd = zip64InfoPtr + zip64InfoSize ;
114- ZL_ASSERT_LE (offsetTrusted , 20 );
115+ ZL_ASSERT_LE (offsetTrusted , 16 );
115116 for (;;) {
116117 ZL_ERR_IF_LT (zip64InfoEnd - zip64InfoPtr , 4 , corruption );
117118 const uint16_t id = ZL_readLE16 (zip64InfoPtr );
@@ -133,12 +134,13 @@ static ZL_RESULT_OF(uint64_t) readZip64Info(
133134 * @returns The size of the CDFH entry or an error.
134135 */
135136static ZL_Report readCentralDirectoryFileHeader (
137+ ZL_OperationContext * opCtx ,
136138 const char * cdfhPtr ,
137139 const char * cdfhEnd ,
138140 uint64_t * localFileHeaderOffset ,
139141 uint64_t * compressedSize )
140142{
141- ZL_RESULT_DECLARE_SCOPE_REPORT (NULL );
143+ ZL_RESULT_DECLARE_SCOPE_REPORT (opCtx );
142144 // suppress -Wmaybe-uninitialized
143145 * localFileHeaderOffset = 0 ;
144146
@@ -155,22 +157,33 @@ static ZL_Report readCentralDirectoryFileHeader(
155157 const char * const extraFieldPtr =
156158 cdfhPtr + kMinCentralDirectoryFileHeaderSize + filenameLength ;
157159
158- * localFileHeaderOffset = read32OrNeg1 (cdfhPtr + 42 );
159- if (* localFileHeaderOffset == (uint64_t )-1 ) {
160- ZL_TRY_LET (
161- uint64_t ,
162- offset ,
163- readZip64Info (extraFieldPtr , extraFieldLength , 16 ));
164- * localFileHeaderOffset = offset ;
160+ // Zip64 extra field stores values in order: uncompressed size,
161+ // compressed size, header offset. Each field is only present when
162+ // the corresponding CDFH field is 0xFFFFFFFF.
163+ size_t zip64Offset = 0 ;
164+ if (ZL_readLE32 (cdfhPtr + 24 ) == (uint32_t )-1 ) {
165+ zip64Offset += 8 ;
165166 }
166167
167168 * compressedSize = read32OrNeg1 (cdfhPtr + 20 );
168169 if (* compressedSize == (uint64_t )-1 ) {
169170 ZL_TRY_LET (
170171 uint64_t ,
171172 size ,
172- readZip64Info (extraFieldPtr , extraFieldLength , 0 ));
173+ readZip64Info (
174+ opCtx , extraFieldPtr , extraFieldLength , zip64Offset ));
173175 * compressedSize = size ;
176+ zip64Offset += 8 ;
177+ }
178+
179+ * localFileHeaderOffset = read32OrNeg1 (cdfhPtr + 42 );
180+ if (* localFileHeaderOffset == (uint64_t )-1 ) {
181+ ZL_TRY_LET (
182+ uint64_t ,
183+ offset ,
184+ readZip64Info (
185+ opCtx , extraFieldPtr , extraFieldLength , zip64Offset ));
186+ * localFileHeaderOffset = offset ;
174187 }
175188
176189 return ZL_returnValue (cdfhLength );
@@ -235,6 +248,7 @@ static bool ZS2_ZipLexer_validateCentralDirectory(
235248 uint64_t localFileHeaderOffset ;
236249 uint64_t compressedSize ;
237250 if (ZL_isError (readCentralDirectoryFileHeader (
251+ lexer -> opCtx ,
238252 centralDirectoryPtr ,
239253 lexer -> srcEnd ,
240254 & localFileHeaderOffset ,
@@ -297,7 +311,7 @@ static ZL_Report ZS2_ZipLexer_findZipBegin(
297311 const char * maxRecordEnd ,
298312 bool (* validate )(const ZS2_ZipLexer * , const char * , const char * ))
299313{
300- ZL_RESULT_DECLARE_SCOPE_REPORT (NULL );
314+ ZL_RESULT_DECLARE_SCOPE_REPORT (lexer -> opCtx );
301315 ZL_ERR_IF_LT (minRecordSize , 4 , corruption );
302316 ZL_ERR_IF_GT (
303317 minRecordSize ,
@@ -346,7 +360,7 @@ static ZL_Report ZS2_ZipLexer_findEOCD64(
346360 const char * eocdPtr ,
347361 ZS2_ZipLexer_EndOfCentralDirectory * eocd )
348362{
349- ZL_RESULT_DECLARE_SCOPE_REPORT (NULL );
363+ ZL_RESULT_DECLARE_SCOPE_REPORT (lexer -> opCtx );
350364 ZL_ASSERT (ZS2_ZipLexer_EndOfCentralDirectory_needZip64 (eocd ));
351365 ZL_ASSERT_GE (eocdPtr , lexer -> zipBegin );
352366 ZL_ASSERT_LE (eocdPtr , lexer -> srcEnd );
@@ -402,7 +416,7 @@ static ZL_Report ZS2_ZipLexer_findEOCD64(
402416 */
403417static ZL_Report ZS2_ZipLexer_parseEOCD (ZS2_ZipLexer * lexer , size_t eocdOffset )
404418{
405- ZL_RESULT_DECLARE_SCOPE_REPORT (NULL );
419+ ZL_RESULT_DECLARE_SCOPE_REPORT (lexer -> opCtx );
406420 ZL_ERR_IF_GT (
407421 eocdOffset , (size_t )(lexer -> srcEnd - lexer -> zipBegin ), corruption );
408422 const char * const eocdPtr = lexer -> zipBegin + eocdOffset ;
@@ -487,6 +501,29 @@ static ZL_Report ZS2_ZipLexer_parseEOCD(ZS2_ZipLexer* lexer, size_t eocdOffset)
487501
488502static ZL_Report ZS2_ZipLexer_setFileState (ZS2_ZipLexer * lexer );
489503
504+ static ZL_Report ZS2_ZipLexer_initWithEOCD (
505+ ZS2_ZipLexer * lexer ,
506+ const void * src ,
507+ size_t srcSize ,
508+ size_t eocdOffset )
509+ {
510+ ZL_RESULT_DECLARE_SCOPE_REPORT (lexer -> opCtx );
511+ lexer -> zipBegin = src ;
512+ lexer -> srcPtr = src ;
513+ lexer -> srcEnd = lexer -> zipBegin + srcSize ;
514+
515+ memset (& lexer -> fileState , 0 , sizeof (lexer -> fileState ));
516+
517+ ZL_ERR_IF_ERR (ZS2_ZipLexer_parseEOCD (lexer , eocdOffset ));
518+
519+ if (lexer -> cdfhIdx < lexer -> cdfhNum ) {
520+ // Proactively initialize the file state to catch more invalid zip files
521+ // in the init() function.
522+ ZL_ERR_IF_ERR (ZS2_ZipLexer_setFileState (lexer ));
523+ }
524+ return ZL_returnSuccess ();
525+ }
526+
490527static bool ZS2_ZipLexer_tryInit (
491528 ZS2_ZipLexer * lexer ,
492529 const void * src ,
@@ -507,10 +544,14 @@ static bool ZS2_ZipLexer_tryInit(
507544 return true;
508545}
509546
510- ZL_Report
511- ZS2_ZipLexer_init (ZS2_ZipLexer * lexer , const void * src , size_t srcSize )
547+ ZL_Report ZS2_ZipLexer_init (
548+ ZS2_ZipLexer * lexer ,
549+ const void * src ,
550+ size_t srcSize ,
551+ ZL_OperationContext * opCtx )
512552{
513- ZL_RESULT_DECLARE_SCOPE_REPORT (NULL );
553+ lexer -> opCtx = opCtx ;
554+ ZL_RESULT_DECLARE_SCOPE_REPORT (lexer -> opCtx );
514555 const size_t minReverseOffset = kMinEndOfCentralDirectoryRecordSize ;
515556 // Maximum allowed offset if there is no garbage at the end
516557 const size_t maxLegalReverseOffset =
@@ -542,29 +583,6 @@ ZS2_ZipLexer_init(ZS2_ZipLexer* lexer, const void* src, size_t srcSize)
542583 return ZL_returnSuccess ();
543584}
544585
545- ZL_Report ZS2_ZipLexer_initWithEOCD (
546- ZS2_ZipLexer * lexer ,
547- const void * src ,
548- size_t srcSize ,
549- size_t eocdOffset )
550- {
551- ZL_RESULT_DECLARE_SCOPE_REPORT (NULL );
552- lexer -> zipBegin = src ;
553- lexer -> srcPtr = src ;
554- lexer -> srcEnd = lexer -> zipBegin + srcSize ;
555-
556- memset (& lexer -> fileState , 0 , sizeof (lexer -> fileState ));
557-
558- ZL_ERR_IF_ERR (ZS2_ZipLexer_parseEOCD (lexer , eocdOffset ));
559-
560- if (lexer -> cdfhIdx < lexer -> cdfhNum ) {
561- // Proactively initialize the file state to catch more invalid zip files
562- // in the init() function.
563- ZL_ERR_IF_ERR (ZS2_ZipLexer_setFileState (lexer ));
564- }
565- return ZL_returnSuccess ();
566- }
567-
568586/**
569587 * Emits an unknown token. This is used for bytes in the Zip file that are
570588 * otherwise unaccounted for. The Zip format, read loosely, allows for gaps in
@@ -578,7 +596,7 @@ static ZL_Report ZS2_ZipLexer_lexUnknown(
578596 ZS2_ZipToken * out ,
579597 const char * nextPtr )
580598{
581- ZL_RESULT_DECLARE_SCOPE_REPORT (NULL );
599+ ZL_RESULT_DECLARE_SCOPE_REPORT (lexer -> opCtx );
582600 ZL_ASSERT_GT (nextPtr , lexer -> srcPtr );
583601 ZL_ASSERT_LE (nextPtr , lexer -> srcEnd );
584602
@@ -612,7 +630,7 @@ static ZL_Report ZS2_ZipLexer_lexSection(
612630 const char * * sectionPtrPtr ,
613631 size_t sectionSize )
614632{
615- ZL_RESULT_DECLARE_SCOPE_REPORT (NULL );
633+ ZL_RESULT_DECLARE_SCOPE_REPORT (lexer -> opCtx );
616634 // Ensure the srcPtr is at the beginning of the section
617635 if (lexer -> srcPtr < * sectionPtrPtr ) {
618636 return ZS2_ZipLexer_lexUnknown (lexer , out , * sectionPtrPtr );
@@ -634,7 +652,7 @@ static ZL_Report ZS2_ZipLexer_lexSection(
634652/// Handles emitting tokens for all sections after the files.
635653static ZL_Report ZS2_ZipLexer_lexTail (ZS2_ZipLexer * lexer , ZS2_ZipToken * out )
636654{
637- ZL_RESULT_DECLARE_SCOPE_REPORT (NULL );
655+ ZL_RESULT_DECLARE_SCOPE_REPORT (lexer -> opCtx );
638656 ZL_ERR_IF_NE (lexer -> cdfhPtr , lexer -> cdfhEnd , corruption );
639657
640658 memset (out , 0 , sizeof (* out ));
@@ -691,12 +709,13 @@ static ZL_Report ZS2_ZipLexer_readNextCentralDirectoryFileHeader(
691709 uint64_t * localFileHeaderOffset ,
692710 uint64_t * compressedSize )
693711{
694- ZL_RESULT_DECLARE_SCOPE_REPORT (NULL );
712+ ZL_RESULT_DECLARE_SCOPE_REPORT (lexer -> opCtx );
695713 ZL_ASSERT_LT (lexer -> cdfhIdx , lexer -> cdfhNum );
696714 ZL_TRY_LET (
697715 size_t ,
698716 cdfhLength ,
699717 readCentralDirectoryFileHeader (
718+ lexer -> opCtx ,
700719 lexer -> cdfhPtr ,
701720 lexer -> cdfhEnd ,
702721 localFileHeaderOffset ,
@@ -723,7 +742,7 @@ static bool ZS2_ZipLexer_FileState_empty(
723742 */
724743static ZL_Report ZS2_ZipLexer_setFileState (ZS2_ZipLexer * lexer )
725744{
726- ZL_RESULT_DECLARE_SCOPE_REPORT (NULL );
745+ ZL_RESULT_DECLARE_SCOPE_REPORT (lexer -> opCtx );
727746 ZL_ASSERT (ZS2_ZipLexer_FileState_empty (& lexer -> fileState ));
728747
729748 // Read fields from the CDFH. The compressed size is read from the CDFH,
@@ -796,7 +815,7 @@ static ZL_Report ZS2_ZipLexer_setFileState(ZS2_ZipLexer* lexer)
796815
797816static ZL_Report ZS2_ZipLexer_lexFile (ZS2_ZipLexer * lexer , ZS2_ZipToken * out )
798817{
799- ZL_RESULT_DECLARE_SCOPE_REPORT (NULL );
818+ ZL_RESULT_DECLARE_SCOPE_REPORT (lexer -> opCtx );
800819 ZL_ASSERT_LE (lexer -> cdfhIdx , lexer -> cdfhNum );
801820 ZL_ASSERT_LE (lexer -> cdfhPtr , lexer -> cdfhEnd );
802821
@@ -859,7 +878,7 @@ static ZL_Report ZS2_ZipLexer_lexOne(ZS2_ZipLexer* lexer, ZS2_ZipToken* out)
859878ZL_Report
860879ZS2_ZipLexer_lex (ZS2_ZipLexer * lexer , ZS2_ZipToken * out , size_t outCapacity )
861880{
862- ZL_RESULT_DECLARE_SCOPE_REPORT (NULL );
881+ ZL_RESULT_DECLARE_SCOPE_REPORT (lexer -> opCtx );
863882 size_t entries ;
864883 for (entries = 0 ; !ZS2_ZipLexer_finished (lexer ) && entries < outCapacity ;
865884 ++ entries ) {
@@ -886,6 +905,6 @@ size_t ZS2_ZipLexer_numFiles(const ZS2_ZipLexer* lexer)
886905bool ZS2_isLikelyZipFile (const void * src , size_t srcSize )
887906{
888907 ZS2_ZipLexer lexer ;
889- const ZL_Report report = ZS2_ZipLexer_init (& lexer , src , srcSize );
908+ const ZL_Report report = ZS2_ZipLexer_init (& lexer , src , srcSize , NULL );
890909 return !ZL_isError (report );
891910}
0 commit comments