Skip to content

Commit e4a76c0

Browse files
committed
fix(handler): add support for zip64 values in Central Directory Headers
1 parent fb8c965 commit e4a76c0

File tree

9 files changed

+53
-3
lines changed

9 files changed

+53
-3
lines changed
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
version https://git-lfs.github.com/spec/v1
2+
oid sha256:a59995571929d2047445ef9ead25ebe1560a6b52a8204ed342c72f8eb624bec9
3+
size 457
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
version https://git-lfs.github.com/spec/v1
2+
oid sha256:cca8132ff6bf4a712056e15507643bb32ddd1283cf84d85157c9c2a299cf6749
3+
size 1481
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
version https://git-lfs.github.com/spec/v1
2+
oid sha256:a0bee6616b5e5eae6799cb4525a884a82e7161614f11122bbdf4383b2ac05998
3+
size 5
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
version https://git-lfs.github.com/spec/v1
2+
oid sha256:6ace33171ce0acb6891e3cc311d75a97aa429d77c05cba600d49ed9652ed49de
3+
size 4
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
version https://git-lfs.github.com/spec/v1
2+
oid sha256:7fdac534f308dcc7708b640a33ace78c5cffb61a90d425b07409f0b66056bee0
3+
size 1024
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
version https://git-lfs.github.com/spec/v1
2+
oid sha256:a59995571929d2047445ef9ead25ebe1560a6b52a8204ed342c72f8eb624bec9
3+
size 457
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
version https://git-lfs.github.com/spec/v1
2+
oid sha256:a0bee6616b5e5eae6799cb4525a884a82e7161614f11122bbdf4383b2ac05998
3+
size 5
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
version https://git-lfs.github.com/spec/v1
2+
oid sha256:6ace33171ce0acb6891e3cc311d75a97aa429d77c05cba600d49ed9652ed49de
3+
size 4

unblob/handlers/archive/zip.py

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,8 @@ class ZIPHandler(StructHandler):
3636
uint16 internal_file_attr;
3737
uint32 external_file_attr;
3838
uint32 relative_offset_local_header;
39-
char file_name[file_name_length];
40-
char extra_field[extra_field_length];
39+
// char file_name[file_name_length];
40+
// char extra_field[extra_field_length];
4141
} cd_file_header_t;
4242

4343
typedef struct end_of_central_directory
@@ -95,6 +95,9 @@ def has_encrypted_files(
9595
file.seek(start_offset + end_of_central_directory.offset_of_cd, io.SEEK_SET)
9696
for _ in range(end_of_central_directory.total_entries):
9797
cd_header = self.cparser_le.cd_file_header_t(file)
98+
file.seek(
99+
cd_header.file_name_length + cd_header.extra_field_length, io.SEEK_CUR
100+
)
98101
if cd_header.flags & self.ENCRYPTED_FLAG:
99102
return True
100103
return False
@@ -111,6 +114,14 @@ def is_zip64_eocd(end_of_central_directory: Instance):
111114
or end_of_central_directory.offset_of_cd == 0xFFFFFFFF
112115
)
113116

117+
@staticmethod
118+
def is_zip64_cd(central_directory: Instance):
119+
# see https://pkware.cachefly.net/webdocs/casestudies/APPNOTE.TXT section 4.3.9.2
120+
return (
121+
central_directory.file_size == 0xFFFFFFFF
122+
or central_directory.compress_size == 0xFFFFFFFF
123+
)
124+
114125
def _parse_zip64(self, file: File, start_offset: int, offset: int) -> Instance:
115126
file.seek(start_offset, io.SEEK_SET)
116127
for eocd_locator_offset in iterate_patterns(
@@ -137,6 +148,20 @@ def _parse_zip64(self, file: File, start_offset: int, offset: int) -> Instance:
137148
"Missing ZIP64 EOCD locator record header in ZIP chunk."
138149
)
139150

151+
def is_zip64(self, file, start_offset, offset, end_of_central_directory):
152+
absolute_offset_of_cd = start_offset + end_of_central_directory.offset_of_cd
153+
154+
if 0 < absolute_offset_of_cd < offset:
155+
file.seek(absolute_offset_of_cd, io.SEEK_SET)
156+
central_directory = self.cparser_le.cd_file_header_t(file)
157+
if self.is_zip64_cd(central_directory):
158+
return True
159+
160+
# some values in the CD can be FFFF, indicating its a zip64
161+
# if the offset of the CD is 0xFFFFFFFF, its definitely one
162+
# otherwise we check every other header indicating zip64
163+
return self.is_zip64_eocd(end_of_central_directory)
164+
140165
def calculate_chunk(self, file: File, start_offset: int) -> Optional[ValidChunk]:
141166
has_encrypted_files = False
142167
file.seek(start_offset, io.SEEK_SET)
@@ -147,7 +172,8 @@ def calculate_chunk(self, file: File, start_offset: int) -> Optional[ValidChunk]
147172
file.seek(offset, io.SEEK_SET)
148173
end_of_central_directory = self.parse_header(file)
149174

150-
if self.is_zip64_eocd(end_of_central_directory):
175+
if self.is_zip64(file, start_offset, offset, end_of_central_directory):
176+
file.seek(offset, io.SEEK_SET)
151177
end_of_central_directory = self._parse_zip64(file, start_offset, offset)
152178
break
153179

0 commit comments

Comments
 (0)