blob: cb72f0e9b29a40b0df0b2083ece8df765dcdcaf7 [file] [log] [blame]
Narayan Kamath7462f022013-11-21 13:05:04 +00001/*
2 * Copyright (C) 2013 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Narayan Kamath1ef9d2d2017-06-15 13:58:25 +010017#include "zip_archive_private.h"
18
Narayan Kamath00a258c2013-12-13 16:06:19 +000019#include <errno.h>
Dmitriy Ivanov40b52b22014-07-15 19:33:00 -070020#include <fcntl.h>
Narayan Kamath00a258c2013-12-13 16:06:19 +000021#include <getopt.h>
Narayan Kamath7462f022013-11-21 13:05:04 +000022#include <stdio.h>
Christopher Ferrise6884ce2015-11-10 14:55:12 -080023#include <string.h>
Narayan Kamath00a258c2013-12-13 16:06:19 +000024#include <unistd.h>
Christopher Ferrise6884ce2015-11-10 14:55:12 -080025
Yabin Cui8e6f7222016-02-08 16:26:33 -080026#include <memory>
Narayan Kamath00a258c2013-12-13 16:06:19 +000027#include <vector>
28
Elliott Hughes4f713192015-12-04 22:00:26 -080029#include <android-base/file.h>
Yabin Cui8e6f7222016-02-08 16:26:33 -080030#include <android-base/test_utils.h>
Tianjie Xu18c25922016-09-29 15:27:41 -070031#include <android-base/unique_fd.h>
Narayan Kamath7462f022013-11-21 13:05:04 +000032#include <gtest/gtest.h>
Tianjie Xu18c25922016-09-29 15:27:41 -070033#include <utils/FileMap.h>
Christopher Ferrise6884ce2015-11-10 14:55:12 -080034#include <ziparchive/zip_archive.h>
35#include <ziparchive/zip_archive_stream_entry.h>
Narayan Kamath7462f022013-11-21 13:05:04 +000036
Narayan Kamath58aaf462013-12-10 16:47:14 +000037static std::string test_data_dir;
Narayan Kamath7462f022013-11-21 13:05:04 +000038
Neil Fullerb1a113f2014-07-25 14:43:04 +010039static const std::string kMissingZip = "missing.zip";
Narayan Kamath58aaf462013-12-10 16:47:14 +000040static const std::string kValidZip = "valid.zip";
Christopher Ferrise6884ce2015-11-10 14:55:12 -080041static const std::string kLargeZip = "large.zip";
42static const std::string kBadCrcZip = "bad_crc.zip";
Tianjie Xufba1a362016-09-21 14:58:11 -070043static const std::string kCrashApk = "crash.apk";
Tianjie Xu9e020e22016-10-10 12:11:30 -070044static const std::string kBadFilenameZip = "bad_filename.zip";
Tianjie Xu18c25922016-09-29 15:27:41 -070045static const std::string kUpdateZip = "dummy-update.zip";
Narayan Kamath58aaf462013-12-10 16:47:14 +000046
Jiyong Parkcd997e62017-06-30 17:23:33 +090047static const std::vector<uint8_t> kATxtContents{'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'a',
48 'b', 'c', 'd', 'e', 'f', 'g', 'h', '\n'};
Narayan Kamath58aaf462013-12-10 16:47:14 +000049
Jiyong Parkcd997e62017-06-30 17:23:33 +090050static const std::vector<uint8_t> kATxtContentsCompressed{'K', 'L', 'J', 'N', 'I', 'M', 'K',
51 207, 'H', 132, 210, '\\', '\0'};
Christopher Ferrise6884ce2015-11-10 14:55:12 -080052
Jiyong Parkcd997e62017-06-30 17:23:33 +090053static const std::vector<uint8_t> kBTxtContents{'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', '\n'};
Narayan Kamath58aaf462013-12-10 16:47:14 +000054
Christopher Ferrise6884ce2015-11-10 14:55:12 -080055static const std::string kATxtName("a.txt");
56static const std::string kBTxtName("b.txt");
57static const std::string kNonexistentTxtName("nonexistent.txt");
58static const std::string kEmptyTxtName("empty.txt");
59static const std::string kLargeCompressTxtName("compress.txt");
60static const std::string kLargeUncompressTxtName("uncompress.txt");
Piotr Jastrzebskiecccc5a2014-08-11 16:35:11 +010061
Jiyong Parkcd997e62017-06-30 17:23:33 +090062static int32_t OpenArchiveWrapper(const std::string& name, ZipArchiveHandle* handle) {
Narayan Kamath58aaf462013-12-10 16:47:14 +000063 const std::string abs_path = test_data_dir + "/" + name;
64 return OpenArchive(abs_path.c_str(), handle);
65}
66
Jiyong Parkcd997e62017-06-30 17:23:33 +090067static void AssertNameEquals(const std::string& name_str, const ZipString& name) {
Narayan Kamath58aaf462013-12-10 16:47:14 +000068 ASSERT_EQ(name_str.size(), name.name_length);
69 ASSERT_EQ(0, memcmp(name_str.c_str(), name.name, name.name_length));
70}
71
Christopher Ferrise6884ce2015-11-10 14:55:12 -080072static void SetZipString(ZipString* zip_str, const std::string& str) {
73 zip_str->name = reinterpret_cast<const uint8_t*>(str.c_str());
74 zip_str->name_length = str.size();
75}
76
Narayan Kamath58aaf462013-12-10 16:47:14 +000077TEST(ziparchive, Open) {
78 ZipArchiveHandle handle;
79 ASSERT_EQ(0, OpenArchiveWrapper(kValidZip, &handle));
Tianjie Xu9e020e22016-10-10 12:11:30 -070080 CloseArchive(handle);
Narayan Kamath58aaf462013-12-10 16:47:14 +000081
Tianjie Xu9e020e22016-10-10 12:11:30 -070082 ASSERT_EQ(-1, OpenArchiveWrapper(kBadFilenameZip, &handle));
Narayan Kamath58aaf462013-12-10 16:47:14 +000083 CloseArchive(handle);
84}
85
Tianjie Xufba1a362016-09-21 14:58:11 -070086TEST(ziparchive, OutOfBound) {
87 ZipArchiveHandle handle;
88 ASSERT_EQ(-8, OpenArchiveWrapper(kCrashApk, &handle));
89 CloseArchive(handle);
90}
91
Neil Fullerb1a113f2014-07-25 14:43:04 +010092TEST(ziparchive, OpenMissing) {
93 ZipArchiveHandle handle;
94 ASSERT_NE(0, OpenArchiveWrapper(kMissingZip, &handle));
95
96 // Confirm the file descriptor is not going to be mistaken for a valid one.
97 ASSERT_EQ(-1, GetFileDescriptor(handle));
98}
99
Dmitriy Ivanov40b52b22014-07-15 19:33:00 -0700100TEST(ziparchive, OpenAssumeFdOwnership) {
Yabin Cui8e6f7222016-02-08 16:26:33 -0800101 int fd = open((test_data_dir + "/" + kValidZip).c_str(), O_RDONLY | O_BINARY);
Dmitriy Ivanov40b52b22014-07-15 19:33:00 -0700102 ASSERT_NE(-1, fd);
103 ZipArchiveHandle handle;
104 ASSERT_EQ(0, OpenArchiveFd(fd, "OpenWithAssumeFdOwnership", &handle));
105 CloseArchive(handle);
106 ASSERT_EQ(-1, lseek(fd, 0, SEEK_SET));
107 ASSERT_EQ(EBADF, errno);
108}
109
110TEST(ziparchive, OpenDoNotAssumeFdOwnership) {
Yabin Cui8e6f7222016-02-08 16:26:33 -0800111 int fd = open((test_data_dir + "/" + kValidZip).c_str(), O_RDONLY | O_BINARY);
Dmitriy Ivanov40b52b22014-07-15 19:33:00 -0700112 ASSERT_NE(-1, fd);
113 ZipArchiveHandle handle;
114 ASSERT_EQ(0, OpenArchiveFd(fd, "OpenWithAssumeFdOwnership", &handle, false));
115 CloseArchive(handle);
116 ASSERT_EQ(0, lseek(fd, 0, SEEK_SET));
117 close(fd);
118}
119
Narayan Kamath58aaf462013-12-10 16:47:14 +0000120TEST(ziparchive, Iteration) {
121 ZipArchiveHandle handle;
122 ASSERT_EQ(0, OpenArchiveWrapper(kValidZip, &handle));
123
124 void* iteration_cookie;
Christopher Ferrise6884ce2015-11-10 14:55:12 -0800125 ASSERT_EQ(0, StartIteration(handle, &iteration_cookie, nullptr, nullptr));
Narayan Kamath7462f022013-11-21 13:05:04 +0000126
127 ZipEntry data;
Yusuke Sato07447542015-06-25 14:39:19 -0700128 ZipString name;
Narayan Kamath58aaf462013-12-10 16:47:14 +0000129
130 // b/c.txt
131 ASSERT_EQ(0, Next(iteration_cookie, &data, &name));
132 AssertNameEquals("b/c.txt", name);
133
134 // b/d.txt
135 ASSERT_EQ(0, Next(iteration_cookie, &data, &name));
136 AssertNameEquals("b/d.txt", name);
137
138 // a.txt
139 ASSERT_EQ(0, Next(iteration_cookie, &data, &name));
140 AssertNameEquals("a.txt", name);
141
142 // b.txt
143 ASSERT_EQ(0, Next(iteration_cookie, &data, &name));
144 AssertNameEquals("b.txt", name);
145
146 // b/
147 ASSERT_EQ(0, Next(iteration_cookie, &data, &name));
148 AssertNameEquals("b/", name);
149
150 // End of iteration.
151 ASSERT_EQ(-1, Next(iteration_cookie, &data, &name));
152
153 CloseArchive(handle);
154}
155
Yusuke Satof1d3d3b2015-06-25 14:09:00 -0700156TEST(ziparchive, IterationWithPrefix) {
157 ZipArchiveHandle handle;
158 ASSERT_EQ(0, OpenArchiveWrapper(kValidZip, &handle));
159
160 void* iteration_cookie;
Yusuke Sato07447542015-06-25 14:39:19 -0700161 ZipString prefix("b/");
Christopher Ferrise6884ce2015-11-10 14:55:12 -0800162 ASSERT_EQ(0, StartIteration(handle, &iteration_cookie, &prefix, nullptr));
Yusuke Satof1d3d3b2015-06-25 14:09:00 -0700163
164 ZipEntry data;
Yusuke Sato07447542015-06-25 14:39:19 -0700165 ZipString name;
Yusuke Satof1d3d3b2015-06-25 14:09:00 -0700166
167 // b/c.txt
168 ASSERT_EQ(0, Next(iteration_cookie, &data, &name));
169 AssertNameEquals("b/c.txt", name);
170
171 // b/d.txt
172 ASSERT_EQ(0, Next(iteration_cookie, &data, &name));
173 AssertNameEquals("b/d.txt", name);
174
175 // b/
176 ASSERT_EQ(0, Next(iteration_cookie, &data, &name));
177 AssertNameEquals("b/", name);
178
179 // End of iteration.
180 ASSERT_EQ(-1, Next(iteration_cookie, &data, &name));
181
182 CloseArchive(handle);
183}
184
185TEST(ziparchive, IterationWithSuffix) {
186 ZipArchiveHandle handle;
187 ASSERT_EQ(0, OpenArchiveWrapper(kValidZip, &handle));
188
189 void* iteration_cookie;
Yusuke Sato07447542015-06-25 14:39:19 -0700190 ZipString suffix(".txt");
Christopher Ferrise6884ce2015-11-10 14:55:12 -0800191 ASSERT_EQ(0, StartIteration(handle, &iteration_cookie, nullptr, &suffix));
Yusuke Satof1d3d3b2015-06-25 14:09:00 -0700192
193 ZipEntry data;
Yusuke Sato07447542015-06-25 14:39:19 -0700194 ZipString name;
Yusuke Satof1d3d3b2015-06-25 14:09:00 -0700195
196 // b/c.txt
197 ASSERT_EQ(0, Next(iteration_cookie, &data, &name));
198 AssertNameEquals("b/c.txt", name);
199
200 // b/d.txt
201 ASSERT_EQ(0, Next(iteration_cookie, &data, &name));
202 AssertNameEquals("b/d.txt", name);
203
204 // a.txt
205 ASSERT_EQ(0, Next(iteration_cookie, &data, &name));
206 AssertNameEquals("a.txt", name);
207
208 // b.txt
209 ASSERT_EQ(0, Next(iteration_cookie, &data, &name));
210 AssertNameEquals("b.txt", name);
211
212 // End of iteration.
213 ASSERT_EQ(-1, Next(iteration_cookie, &data, &name));
214
215 CloseArchive(handle);
216}
217
218TEST(ziparchive, IterationWithPrefixAndSuffix) {
219 ZipArchiveHandle handle;
220 ASSERT_EQ(0, OpenArchiveWrapper(kValidZip, &handle));
221
222 void* iteration_cookie;
Yusuke Sato07447542015-06-25 14:39:19 -0700223 ZipString prefix("b");
224 ZipString suffix(".txt");
Yusuke Satof1d3d3b2015-06-25 14:09:00 -0700225 ASSERT_EQ(0, StartIteration(handle, &iteration_cookie, &prefix, &suffix));
226
227 ZipEntry data;
Yusuke Sato07447542015-06-25 14:39:19 -0700228 ZipString name;
Yusuke Satof1d3d3b2015-06-25 14:09:00 -0700229
230 // b/c.txt
231 ASSERT_EQ(0, Next(iteration_cookie, &data, &name));
232 AssertNameEquals("b/c.txt", name);
233
234 // b/d.txt
235 ASSERT_EQ(0, Next(iteration_cookie, &data, &name));
236 AssertNameEquals("b/d.txt", name);
237
238 // b.txt
239 ASSERT_EQ(0, Next(iteration_cookie, &data, &name));
240 AssertNameEquals("b.txt", name);
241
242 // End of iteration.
243 ASSERT_EQ(-1, Next(iteration_cookie, &data, &name));
244
245 CloseArchive(handle);
246}
247
248TEST(ziparchive, IterationWithBadPrefixAndSuffix) {
249 ZipArchiveHandle handle;
250 ASSERT_EQ(0, OpenArchiveWrapper(kValidZip, &handle));
251
252 void* iteration_cookie;
Yusuke Sato07447542015-06-25 14:39:19 -0700253 ZipString prefix("x");
254 ZipString suffix("y");
Yusuke Satof1d3d3b2015-06-25 14:09:00 -0700255 ASSERT_EQ(0, StartIteration(handle, &iteration_cookie, &prefix, &suffix));
256
257 ZipEntry data;
Yusuke Sato07447542015-06-25 14:39:19 -0700258 ZipString name;
Yusuke Satof1d3d3b2015-06-25 14:09:00 -0700259
260 // End of iteration.
261 ASSERT_EQ(-1, Next(iteration_cookie, &data, &name));
262
263 CloseArchive(handle);
264}
265
Narayan Kamath58aaf462013-12-10 16:47:14 +0000266TEST(ziparchive, FindEntry) {
267 ZipArchiveHandle handle;
268 ASSERT_EQ(0, OpenArchiveWrapper(kValidZip, &handle));
269
270 ZipEntry data;
Yusuke Sato07447542015-06-25 14:39:19 -0700271 ZipString name;
Christopher Ferrise6884ce2015-11-10 14:55:12 -0800272 SetZipString(&name, kATxtName);
Piotr Jastrzebskiecccc5a2014-08-11 16:35:11 +0100273 ASSERT_EQ(0, FindEntry(handle, name, &data));
Narayan Kamath58aaf462013-12-10 16:47:14 +0000274
275 // Known facts about a.txt, from zipinfo -v.
276 ASSERT_EQ(63, data.offset);
277 ASSERT_EQ(kCompressDeflated, data.method);
278 ASSERT_EQ(static_cast<uint32_t>(17), data.uncompressed_length);
279 ASSERT_EQ(static_cast<uint32_t>(13), data.compressed_length);
280 ASSERT_EQ(0x950821c5, data.crc32);
beonit0e99a2f2015-07-18 02:08:16 +0900281 ASSERT_EQ(static_cast<uint32_t>(0x438a8005), data.mod_time);
Narayan Kamath58aaf462013-12-10 16:47:14 +0000282
283 // An entry that doesn't exist. Should be a negative return code.
Yusuke Sato07447542015-06-25 14:39:19 -0700284 ZipString absent_name;
Christopher Ferrise6884ce2015-11-10 14:55:12 -0800285 SetZipString(&absent_name, kNonexistentTxtName);
Piotr Jastrzebskiecccc5a2014-08-11 16:35:11 +0100286 ASSERT_LT(FindEntry(handle, absent_name, &data), 0);
Narayan Kamath58aaf462013-12-10 16:47:14 +0000287
288 CloseArchive(handle);
289}
290
Mykola Kondratenko50afc152014-09-08 12:46:37 +0200291TEST(ziparchive, TestInvalidDeclaredLength) {
292 ZipArchiveHandle handle;
293 ASSERT_EQ(0, OpenArchiveWrapper("declaredlength.zip", &handle));
294
295 void* iteration_cookie;
Christopher Ferrise6884ce2015-11-10 14:55:12 -0800296 ASSERT_EQ(0, StartIteration(handle, &iteration_cookie, nullptr, nullptr));
Mykola Kondratenko50afc152014-09-08 12:46:37 +0200297
Yusuke Sato07447542015-06-25 14:39:19 -0700298 ZipString name;
Mykola Kondratenko50afc152014-09-08 12:46:37 +0200299 ZipEntry data;
300
301 ASSERT_EQ(Next(iteration_cookie, &data, &name), 0);
302 ASSERT_EQ(Next(iteration_cookie, &data, &name), 0);
303
304 CloseArchive(handle);
305}
306
Narayan Kamath58aaf462013-12-10 16:47:14 +0000307TEST(ziparchive, ExtractToMemory) {
308 ZipArchiveHandle handle;
309 ASSERT_EQ(0, OpenArchiveWrapper(kValidZip, &handle));
310
311 // An entry that's deflated.
312 ZipEntry data;
Yusuke Sato07447542015-06-25 14:39:19 -0700313 ZipString a_name;
Christopher Ferrise6884ce2015-11-10 14:55:12 -0800314 SetZipString(&a_name, kATxtName);
Piotr Jastrzebskiecccc5a2014-08-11 16:35:11 +0100315 ASSERT_EQ(0, FindEntry(handle, a_name, &data));
Narayan Kamath58aaf462013-12-10 16:47:14 +0000316 const uint32_t a_size = data.uncompressed_length;
Christopher Ferrise6884ce2015-11-10 14:55:12 -0800317 ASSERT_EQ(a_size, kATxtContents.size());
Narayan Kamath58aaf462013-12-10 16:47:14 +0000318 uint8_t* buffer = new uint8_t[a_size];
319 ASSERT_EQ(0, ExtractToMemory(handle, &data, buffer, a_size));
Christopher Ferrise6884ce2015-11-10 14:55:12 -0800320 ASSERT_EQ(0, memcmp(buffer, kATxtContents.data(), a_size));
Narayan Kamath58aaf462013-12-10 16:47:14 +0000321 delete[] buffer;
322
323 // An entry that's stored.
Yusuke Sato07447542015-06-25 14:39:19 -0700324 ZipString b_name;
Christopher Ferrise6884ce2015-11-10 14:55:12 -0800325 SetZipString(&b_name, kBTxtName);
Piotr Jastrzebskiecccc5a2014-08-11 16:35:11 +0100326 ASSERT_EQ(0, FindEntry(handle, b_name, &data));
Narayan Kamath58aaf462013-12-10 16:47:14 +0000327 const uint32_t b_size = data.uncompressed_length;
Christopher Ferrise6884ce2015-11-10 14:55:12 -0800328 ASSERT_EQ(b_size, kBTxtContents.size());
Narayan Kamath58aaf462013-12-10 16:47:14 +0000329 buffer = new uint8_t[b_size];
330 ASSERT_EQ(0, ExtractToMemory(handle, &data, buffer, b_size));
Christopher Ferrise6884ce2015-11-10 14:55:12 -0800331 ASSERT_EQ(0, memcmp(buffer, kBTxtContents.data(), b_size));
Narayan Kamath58aaf462013-12-10 16:47:14 +0000332 delete[] buffer;
333
334 CloseArchive(handle);
335}
336
Narayan Kamath4f6b4992014-06-03 13:59:23 +0100337static const uint32_t kEmptyEntriesZip[] = {
Jiyong Parkcd997e62017-06-30 17:23:33 +0900338 0x04034b50, 0x0000000a, 0x63600000, 0x00004438, 0x00000000, 0x00000000, 0x00090000,
339 0x6d65001c, 0x2e797470, 0x55747874, 0x03000954, 0x52e25c13, 0x52e25c24, 0x000b7875,
340 0x42890401, 0x88040000, 0x50000013, 0x1e02014b, 0x00000a03, 0x60000000, 0x00443863,
341 0x00000000, 0x00000000, 0x09000000, 0x00001800, 0x00000000, 0xa0000000, 0x00000081,
342 0x706d6500, 0x742e7974, 0x54557478, 0x13030005, 0x7552e25c, 0x01000b78, 0x00428904,
343 0x13880400, 0x4b500000, 0x00000605, 0x00010000, 0x004f0001, 0x00430000, 0x00000000};
Narayan Kamath4f6b4992014-06-03 13:59:23 +0100344
Narayan Kamathf899bd52015-04-17 11:53:14 +0100345// This is a zip file containing a single entry (ab.txt) that contains
346// 90072 repetitions of the string "ab\n" and has an uncompressed length
347// of 270216 bytes.
348static const uint16_t kAbZip[] = {
Jiyong Parkcd997e62017-06-30 17:23:33 +0900349 0x4b50, 0x0403, 0x0014, 0x0000, 0x0008, 0x51d2, 0x4698, 0xc4b0, 0x2cda, 0x011b, 0x0000, 0x1f88,
350 0x0004, 0x0006, 0x001c, 0x6261, 0x742e, 0x7478, 0x5455, 0x0009, 0x7c03, 0x3a09, 0x7c55, 0x3a09,
351 0x7555, 0x0b78, 0x0100, 0x8904, 0x0042, 0x0400, 0x1388, 0x0000, 0xc2ed, 0x0d31, 0x0000, 0x030c,
352 0x7fa0, 0x3b2e, 0x22ff, 0xa2aa, 0x841f, 0x45fc, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555,
353 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555,
354 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555,
355 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555,
356 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555,
357 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555,
358 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555,
359 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555,
360 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555,
361 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555,
362 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555,
363 0x5555, 0x5555, 0x5555, 0x5555, 0xdd55, 0x502c, 0x014b, 0x1e02, 0x1403, 0x0000, 0x0800, 0xd200,
364 0x9851, 0xb046, 0xdac4, 0x1b2c, 0x0001, 0x8800, 0x041f, 0x0600, 0x1800, 0x0000, 0x0000, 0x0100,
365 0x0000, 0xa000, 0x0081, 0x0000, 0x6100, 0x2e62, 0x7874, 0x5574, 0x0554, 0x0300, 0x097c, 0x553a,
366 0x7875, 0x000b, 0x0401, 0x4289, 0x0000, 0x8804, 0x0013, 0x5000, 0x054b, 0x0006, 0x0000, 0x0100,
367 0x0100, 0x4c00, 0x0000, 0x5b00, 0x0001, 0x0000, 0x0000};
Narayan Kamathf899bd52015-04-17 11:53:14 +0100368
Christopher Ferrise6884ce2015-11-10 14:55:12 -0800369static const std::string kAbTxtName("ab.txt");
Narayan Kamathf899bd52015-04-17 11:53:14 +0100370static const size_t kAbUncompressedSize = 270216;
371
Narayan Kamath4f6b4992014-06-03 13:59:23 +0100372TEST(ziparchive, EmptyEntries) {
Yabin Cui8e6f7222016-02-08 16:26:33 -0800373 TemporaryFile tmp_file;
374 ASSERT_NE(-1, tmp_file.fd);
375 ASSERT_TRUE(android::base::WriteFully(tmp_file.fd, kEmptyEntriesZip, sizeof(kEmptyEntriesZip)));
Narayan Kamath48953a12014-01-24 12:32:39 +0000376
377 ZipArchiveHandle handle;
Yabin Cui8e6f7222016-02-08 16:26:33 -0800378 ASSERT_EQ(0, OpenArchiveFd(tmp_file.fd, "EmptyEntriesTest", &handle));
Narayan Kamath48953a12014-01-24 12:32:39 +0000379
380 ZipEntry entry;
Yusuke Sato07447542015-06-25 14:39:19 -0700381 ZipString empty_name;
Christopher Ferrise6884ce2015-11-10 14:55:12 -0800382 SetZipString(&empty_name, kEmptyTxtName);
Piotr Jastrzebskiecccc5a2014-08-11 16:35:11 +0100383 ASSERT_EQ(0, FindEntry(handle, empty_name, &entry));
Narayan Kamath48953a12014-01-24 12:32:39 +0000384 ASSERT_EQ(static_cast<uint32_t>(0), entry.uncompressed_length);
385 uint8_t buffer[1];
386 ASSERT_EQ(0, ExtractToMemory(handle, &entry, buffer, 1));
387
Yabin Cui8e6f7222016-02-08 16:26:33 -0800388 TemporaryFile tmp_output_file;
389 ASSERT_NE(-1, tmp_output_file.fd);
390 ASSERT_EQ(0, ExtractEntryToFile(handle, &entry, tmp_output_file.fd));
Narayan Kamath48953a12014-01-24 12:32:39 +0000391
392 struct stat stat_buf;
Yabin Cui8e6f7222016-02-08 16:26:33 -0800393 ASSERT_EQ(0, fstat(tmp_output_file.fd, &stat_buf));
Narayan Kamath48953a12014-01-24 12:32:39 +0000394 ASSERT_EQ(0, stat_buf.st_size);
Narayan Kamath48953a12014-01-24 12:32:39 +0000395}
396
Narayan Kamathf899bd52015-04-17 11:53:14 +0100397TEST(ziparchive, EntryLargerThan32K) {
Yabin Cui8e6f7222016-02-08 16:26:33 -0800398 TemporaryFile tmp_file;
399 ASSERT_NE(-1, tmp_file.fd);
400 ASSERT_TRUE(android::base::WriteFully(tmp_file.fd, reinterpret_cast<const uint8_t*>(kAbZip),
Jiyong Parkcd997e62017-06-30 17:23:33 +0900401 sizeof(kAbZip) - 1));
Narayan Kamathf899bd52015-04-17 11:53:14 +0100402 ZipArchiveHandle handle;
Yabin Cui8e6f7222016-02-08 16:26:33 -0800403 ASSERT_EQ(0, OpenArchiveFd(tmp_file.fd, "EntryLargerThan32KTest", &handle));
Narayan Kamathf899bd52015-04-17 11:53:14 +0100404
405 ZipEntry entry;
Yusuke Sato07447542015-06-25 14:39:19 -0700406 ZipString ab_name;
Christopher Ferrise6884ce2015-11-10 14:55:12 -0800407 SetZipString(&ab_name, kAbTxtName);
Narayan Kamathf899bd52015-04-17 11:53:14 +0100408 ASSERT_EQ(0, FindEntry(handle, ab_name, &entry));
409 ASSERT_EQ(kAbUncompressedSize, entry.uncompressed_length);
410
411 // Extract the entry to memory.
412 std::vector<uint8_t> buffer(kAbUncompressedSize);
413 ASSERT_EQ(0, ExtractToMemory(handle, &entry, &buffer[0], buffer.size()));
414
415 // Extract the entry to a file.
Yabin Cui8e6f7222016-02-08 16:26:33 -0800416 TemporaryFile tmp_output_file;
417 ASSERT_NE(-1, tmp_output_file.fd);
418 ASSERT_EQ(0, ExtractEntryToFile(handle, &entry, tmp_output_file.fd));
Narayan Kamathf899bd52015-04-17 11:53:14 +0100419
420 // Make sure the extracted file size is as expected.
421 struct stat stat_buf;
Yabin Cui8e6f7222016-02-08 16:26:33 -0800422 ASSERT_EQ(0, fstat(tmp_output_file.fd, &stat_buf));
Narayan Kamathf899bd52015-04-17 11:53:14 +0100423 ASSERT_EQ(kAbUncompressedSize, static_cast<size_t>(stat_buf.st_size));
424
425 // Read the file back to a buffer and make sure the contents are
426 // the same as the memory buffer we extracted directly to.
427 std::vector<uint8_t> file_contents(kAbUncompressedSize);
Yabin Cui8e6f7222016-02-08 16:26:33 -0800428 ASSERT_EQ(0, lseek64(tmp_output_file.fd, 0, SEEK_SET));
Jiyong Parkcd997e62017-06-30 17:23:33 +0900429 ASSERT_TRUE(android::base::ReadFully(tmp_output_file.fd, &file_contents[0], file_contents.size()));
Narayan Kamathf899bd52015-04-17 11:53:14 +0100430 ASSERT_EQ(file_contents, buffer);
431
432 for (int i = 0; i < 90072; ++i) {
433 const uint8_t* line = &file_contents[0] + (3 * i);
434 ASSERT_EQ('a', line[0]);
435 ASSERT_EQ('b', line[1]);
436 ASSERT_EQ('\n', line[2]);
437 }
Narayan Kamathf899bd52015-04-17 11:53:14 +0100438}
439
Narayan Kamath4f6b4992014-06-03 13:59:23 +0100440TEST(ziparchive, TrailerAfterEOCD) {
Yabin Cui8e6f7222016-02-08 16:26:33 -0800441 TemporaryFile tmp_file;
442 ASSERT_NE(-1, tmp_file.fd);
Narayan Kamath4f6b4992014-06-03 13:59:23 +0100443
444 // Create a file with 8 bytes of random garbage.
Jiyong Parkcd997e62017-06-30 17:23:33 +0900445 static const uint8_t trailer[] = {'A', 'n', 'd', 'r', 'o', 'i', 'd', 'z'};
Yabin Cui8e6f7222016-02-08 16:26:33 -0800446 ASSERT_TRUE(android::base::WriteFully(tmp_file.fd, kEmptyEntriesZip, sizeof(kEmptyEntriesZip)));
447 ASSERT_TRUE(android::base::WriteFully(tmp_file.fd, trailer, sizeof(trailer)));
Narayan Kamath4f6b4992014-06-03 13:59:23 +0100448
449 ZipArchiveHandle handle;
Yabin Cui8e6f7222016-02-08 16:26:33 -0800450 ASSERT_GT(0, OpenArchiveFd(tmp_file.fd, "EmptyEntriesTest", &handle));
Narayan Kamath4f6b4992014-06-03 13:59:23 +0100451}
452
Narayan Kamath00a258c2013-12-13 16:06:19 +0000453TEST(ziparchive, ExtractToFile) {
Yabin Cui8e6f7222016-02-08 16:26:33 -0800454 TemporaryFile tmp_file;
455 ASSERT_NE(-1, tmp_file.fd);
Jiyong Parkcd997e62017-06-30 17:23:33 +0900456 const uint8_t data[8] = {'1', '2', '3', '4', '5', '6', '7', '8'};
Yabin Cui8e6f7222016-02-08 16:26:33 -0800457 const size_t data_size = sizeof(data);
Narayan Kamath00a258c2013-12-13 16:06:19 +0000458
Yabin Cui8e6f7222016-02-08 16:26:33 -0800459 ASSERT_TRUE(android::base::WriteFully(tmp_file.fd, data, data_size));
Narayan Kamath00a258c2013-12-13 16:06:19 +0000460
461 ZipArchiveHandle handle;
462 ASSERT_EQ(0, OpenArchiveWrapper(kValidZip, &handle));
463
464 ZipEntry entry;
Yusuke Sato07447542015-06-25 14:39:19 -0700465 ZipString name;
Christopher Ferrise6884ce2015-11-10 14:55:12 -0800466 SetZipString(&name, kATxtName);
Piotr Jastrzebskiecccc5a2014-08-11 16:35:11 +0100467 ASSERT_EQ(0, FindEntry(handle, name, &entry));
Yabin Cui8e6f7222016-02-08 16:26:33 -0800468 ASSERT_EQ(0, ExtractEntryToFile(handle, &entry, tmp_file.fd));
Narayan Kamath00a258c2013-12-13 16:06:19 +0000469
Narayan Kamath00a258c2013-12-13 16:06:19 +0000470 // Assert that the first 8 bytes of the file haven't been clobbered.
471 uint8_t read_buffer[data_size];
Yabin Cui8e6f7222016-02-08 16:26:33 -0800472 ASSERT_EQ(0, lseek64(tmp_file.fd, 0, SEEK_SET));
473 ASSERT_TRUE(android::base::ReadFully(tmp_file.fd, read_buffer, data_size));
Narayan Kamath00a258c2013-12-13 16:06:19 +0000474 ASSERT_EQ(0, memcmp(read_buffer, data, data_size));
475
476 // Assert that the remainder of the file contains the incompressed data.
477 std::vector<uint8_t> uncompressed_data(entry.uncompressed_length);
Jiyong Parkcd997e62017-06-30 17:23:33 +0900478 ASSERT_TRUE(
479 android::base::ReadFully(tmp_file.fd, uncompressed_data.data(), entry.uncompressed_length));
480 ASSERT_EQ(0, memcmp(&uncompressed_data[0], kATxtContents.data(), kATxtContents.size()));
Narayan Kamath00a258c2013-12-13 16:06:19 +0000481
482 // Assert that the total length of the file is sane
Yabin Cui8e6f7222016-02-08 16:26:33 -0800483 ASSERT_EQ(static_cast<ssize_t>(data_size + kATxtContents.size()),
484 lseek64(tmp_file.fd, 0, SEEK_END));
Narayan Kamath00a258c2013-12-13 16:06:19 +0000485}
486
Tianjie Xu18c25922016-09-29 15:27:41 -0700487#if !defined(_WIN32)
488TEST(ziparchive, OpenFromMemory) {
489 const std::string zip_path = test_data_dir + "/" + kUpdateZip;
490 android::base::unique_fd fd(open(zip_path.c_str(), O_RDONLY | O_BINARY));
491 ASSERT_NE(-1, fd);
492 struct stat sb;
493 ASSERT_EQ(0, fstat(fd, &sb));
494
495 // Memory map the file first and open the archive from the memory region.
496 android::FileMap file_map;
Jiyong Parkcd997e62017-06-30 17:23:33 +0900497 file_map.create(zip_path.c_str(), fd, 0 /*offset*/, sb.st_size, true);
Tianjie Xu18c25922016-09-29 15:27:41 -0700498 ZipArchiveHandle handle;
499 ASSERT_EQ(0, OpenArchiveFromMemory(file_map.getDataPtr(), file_map.getDataLength(),
500 zip_path.c_str(), &handle));
501
502 // Assert one entry can be found and extracted correctly.
503 std::string BINARY_PATH("META-INF/com/google/android/update-binary");
504 ZipString binary_path(BINARY_PATH.c_str());
505 ZipEntry binary_entry;
506 ASSERT_EQ(0, FindEntry(handle, binary_path, &binary_entry));
507 TemporaryFile tmp_binary;
508 ASSERT_NE(-1, tmp_binary.fd);
509 ASSERT_EQ(0, ExtractEntryToFile(handle, &binary_entry, tmp_binary.fd));
510}
511#endif
512
Jiyong Parkcd997e62017-06-30 17:23:33 +0900513static void ZipArchiveStreamTest(ZipArchiveHandle& handle, const std::string& entry_name, bool raw,
514 bool verified, ZipEntry* entry, std::vector<uint8_t>* read_data) {
Christopher Ferrise6884ce2015-11-10 14:55:12 -0800515 ZipString name;
516 SetZipString(&name, entry_name);
517 ASSERT_EQ(0, FindEntry(handle, name, entry));
518 std::unique_ptr<ZipArchiveStreamEntry> stream;
519 if (raw) {
520 stream.reset(ZipArchiveStreamEntry::CreateRaw(handle, *entry));
521 if (entry->method == kCompressStored) {
522 read_data->resize(entry->uncompressed_length);
523 } else {
524 read_data->resize(entry->compressed_length);
525 }
526 } else {
527 stream.reset(ZipArchiveStreamEntry::Create(handle, *entry));
528 read_data->resize(entry->uncompressed_length);
529 }
530 uint8_t* read_data_ptr = read_data->data();
531 ASSERT_TRUE(stream.get() != nullptr);
532 const std::vector<uint8_t>* data;
533 uint64_t total_size = 0;
534 while ((data = stream->Read()) != nullptr) {
535 total_size += data->size();
536 memcpy(read_data_ptr, data->data(), data->size());
537 read_data_ptr += data->size();
538 }
539 ASSERT_EQ(verified, stream->Verify());
540 ASSERT_EQ(total_size, read_data->size());
541}
542
Jiyong Parkcd997e62017-06-30 17:23:33 +0900543static void ZipArchiveStreamTestUsingContents(const std::string& zip_file,
544 const std::string& entry_name,
545 const std::vector<uint8_t>& contents, bool raw) {
Christopher Ferrise6884ce2015-11-10 14:55:12 -0800546 ZipArchiveHandle handle;
547 ASSERT_EQ(0, OpenArchiveWrapper(zip_file, &handle));
548
549 ZipEntry entry;
550 std::vector<uint8_t> read_data;
551 ZipArchiveStreamTest(handle, entry_name, raw, true, &entry, &read_data);
552
553 ASSERT_EQ(contents.size(), read_data.size());
554 ASSERT_TRUE(memcmp(read_data.data(), contents.data(), read_data.size()) == 0);
555
556 CloseArchive(handle);
557}
558
Jiyong Parkcd997e62017-06-30 17:23:33 +0900559static void ZipArchiveStreamTestUsingMemory(const std::string& zip_file,
560 const std::string& entry_name) {
Christopher Ferrise6884ce2015-11-10 14:55:12 -0800561 ZipArchiveHandle handle;
562 ASSERT_EQ(0, OpenArchiveWrapper(zip_file, &handle));
563
564 ZipEntry entry;
565 std::vector<uint8_t> read_data;
566 ZipArchiveStreamTest(handle, entry_name, false, true, &entry, &read_data);
567
568 std::vector<uint8_t> cmp_data(entry.uncompressed_length);
569 ASSERT_EQ(entry.uncompressed_length, read_data.size());
570 ASSERT_EQ(0, ExtractToMemory(handle, &entry, cmp_data.data(), cmp_data.size()));
571 ASSERT_TRUE(memcmp(read_data.data(), cmp_data.data(), read_data.size()) == 0);
572
573 CloseArchive(handle);
574}
575
576TEST(ziparchive, StreamCompressed) {
577 ZipArchiveStreamTestUsingContents(kValidZip, kATxtName, kATxtContents, false);
578}
579
580TEST(ziparchive, StreamUncompressed) {
581 ZipArchiveStreamTestUsingContents(kValidZip, kBTxtName, kBTxtContents, false);
582}
583
584TEST(ziparchive, StreamRawCompressed) {
585 ZipArchiveStreamTestUsingContents(kValidZip, kATxtName, kATxtContentsCompressed, true);
586}
587
588TEST(ziparchive, StreamRawUncompressed) {
589 ZipArchiveStreamTestUsingContents(kValidZip, kBTxtName, kBTxtContents, true);
590}
591
592TEST(ziparchive, StreamLargeCompressed) {
593 ZipArchiveStreamTestUsingMemory(kLargeZip, kLargeCompressTxtName);
594}
595
596TEST(ziparchive, StreamLargeUncompressed) {
597 ZipArchiveStreamTestUsingMemory(kLargeZip, kLargeUncompressTxtName);
598}
599
600TEST(ziparchive, StreamCompressedBadCrc) {
601 ZipArchiveHandle handle;
602 ASSERT_EQ(0, OpenArchiveWrapper(kBadCrcZip, &handle));
603
604 ZipEntry entry;
605 std::vector<uint8_t> read_data;
606 ZipArchiveStreamTest(handle, kATxtName, false, false, &entry, &read_data);
607
608 CloseArchive(handle);
609}
610
611TEST(ziparchive, StreamUncompressedBadCrc) {
612 ZipArchiveHandle handle;
613 ASSERT_EQ(0, OpenArchiveWrapper(kBadCrcZip, &handle));
614
615 ZipEntry entry;
616 std::vector<uint8_t> read_data;
617 ZipArchiveStreamTest(handle, kBTxtName, false, false, &entry, &read_data);
618
619 CloseArchive(handle);
620}
621
Narayan Kamath162b7052017-06-05 13:21:12 +0100622// Generated using the following Java program:
623// public static void main(String[] foo) throws Exception {
624// FileOutputStream fos = new
625// FileOutputStream("/tmp/data_descriptor.zip");
626// ZipOutputStream zos = new ZipOutputStream(fos);
627// ZipEntry ze = new ZipEntry("name");
628// ze.setMethod(ZipEntry.DEFLATED);
629// zos.putNextEntry(ze);
630// zos.write("abdcdefghijk".getBytes());
631// zos.closeEntry();
632// zos.close();
633// }
634//
635// cat /tmp/data_descriptor.zip | xxd -i
636//
637static const std::vector<uint8_t> kDataDescriptorZipFile{
638 0x50, 0x4b, 0x03, 0x04, 0x14, 0x00, 0x08, 0x08, 0x08, 0x00, 0x30, 0x59, 0xce, 0x4a, 0x00, 0x00,
639 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x6e, 0x61,
640 0x6d, 0x65, 0x4b, 0x4c, 0x4a, 0x49, 0x4e, 0x49, 0x4d, 0x4b, 0xcf, 0xc8, 0xcc, 0xca, 0x06, 0x00,
641 //[sig---------------], [crc32---------------], [csize---------------], [size----------------]
642 0x50, 0x4b, 0x07, 0x08, 0x3d, 0x4e, 0x0e, 0xf9, 0x0e, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
643 0x50, 0x4b, 0x01, 0x02, 0x14, 0x00, 0x14, 0x00, 0x08, 0x08, 0x08, 0x00, 0x30, 0x59, 0xce, 0x4a,
644 0x3d, 0x4e, 0x0e, 0xf9, 0x0e, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
645 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6e, 0x61,
646 0x6d, 0x65, 0x50, 0x4b, 0x05, 0x06, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x32, 0x00,
647 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00};
648
649// The offsets of the data descriptor in this file, so we can mess with
650// them later in the test.
651static constexpr uint32_t kDataDescriptorOffset = 48;
652static constexpr uint32_t kCSizeOffset = kDataDescriptorOffset + 8;
653static constexpr uint32_t kSizeOffset = kCSizeOffset + 4;
654
655static void ExtractEntryToMemory(const std::vector<uint8_t>& zip_data,
656 std::vector<uint8_t>* entry_out, int32_t* error_code_out) {
657 TemporaryFile tmp_file;
658 ASSERT_NE(-1, tmp_file.fd);
659 ASSERT_TRUE(android::base::WriteFully(tmp_file.fd, &zip_data[0], zip_data.size()));
660 ZipArchiveHandle handle;
661 ASSERT_EQ(0, OpenArchiveFd(tmp_file.fd, "ExtractEntryToMemory", &handle));
662
663 // This function expects a variant of kDataDescriptorZipFile, for look for
664 // an entry whose name is "name" and whose size is 12 (contents =
665 // "abdcdefghijk").
666 ZipEntry entry;
667 ZipString empty_name;
668 SetZipString(&empty_name, "name");
669
670 ASSERT_EQ(0, FindEntry(handle, empty_name, &entry));
671 ASSERT_EQ(static_cast<uint32_t>(12), entry.uncompressed_length);
672
673 entry_out->resize(12);
674 (*error_code_out) = ExtractToMemory(handle, &entry, &((*entry_out)[0]), 12);
675
676 CloseArchive(handle);
677}
678
679TEST(ziparchive, ValidDataDescriptors) {
680 std::vector<uint8_t> entry;
681 int32_t error_code = 0;
682 ExtractEntryToMemory(kDataDescriptorZipFile, &entry, &error_code);
683
684 ASSERT_EQ(0, error_code);
685 ASSERT_EQ(12u, entry.size());
686 ASSERT_EQ('a', entry[0]);
687 ASSERT_EQ('k', entry[11]);
688}
689
690TEST(ziparchive, InvalidDataDescriptors) {
691 std::vector<uint8_t> invalid_csize = kDataDescriptorZipFile;
692 invalid_csize[kCSizeOffset] = 0xfe;
693
694 std::vector<uint8_t> entry;
695 int32_t error_code = 0;
696 ExtractEntryToMemory(invalid_csize, &entry, &error_code);
697
Narayan Kamath1ef9d2d2017-06-15 13:58:25 +0100698 ASSERT_EQ(kInconsistentInformation, error_code);
Narayan Kamath162b7052017-06-05 13:21:12 +0100699
700 std::vector<uint8_t> invalid_size = kDataDescriptorZipFile;
701 invalid_csize[kSizeOffset] = 0xfe;
702
703 error_code = 0;
704 entry.clear();
705 ExtractEntryToMemory(invalid_csize, &entry, &error_code);
706
Narayan Kamath1ef9d2d2017-06-15 13:58:25 +0100707 ASSERT_EQ(kInconsistentInformation, error_code);
708}
709
710TEST(ziparchive, ErrorCodeString) {
711 ASSERT_STREQ("Success", ErrorCodeString(0));
712
713 // Out of bounds.
714 ASSERT_STREQ("Unknown return code", ErrorCodeString(1));
715 ASSERT_STREQ("Unknown return code", ErrorCodeString(-13));
716
717 ASSERT_STREQ("I/O error", ErrorCodeString(kIoError));
Narayan Kamath162b7052017-06-05 13:21:12 +0100718}
719
Narayan Kamath2d1e23f2017-10-30 11:17:28 +0000720class VectorReader : public zip_archive::Reader {
721 public:
722 VectorReader(const std::vector<uint8_t>& input) : Reader(), input_(input) {}
723
724 bool ReadAtOffset(uint8_t* buf, size_t len, uint32_t offset) const {
725 if ((offset + len) < input_.size()) {
726 return false;
727 }
728
729 memcpy(buf, &input_[offset], len);
730 return true;
731 }
732
733 private:
734 const std::vector<uint8_t>& input_;
735};
736
737class VectorWriter : public zip_archive::Writer {
738 public:
739 VectorWriter() : Writer() {}
740
741 bool Append(uint8_t* buf, size_t size) {
742 output_.insert(output_.end(), buf, buf + size);
743 return true;
744 }
745
746 std::vector<uint8_t>& GetOutput() { return output_; }
747
748 private:
749 std::vector<uint8_t> output_;
750};
751
752class BadReader : public zip_archive::Reader {
753 public:
754 BadReader() : Reader() {}
755
756 bool ReadAtOffset(uint8_t*, size_t, uint32_t) const { return false; }
757};
758
759class BadWriter : public zip_archive::Writer {
760 public:
761 BadWriter() : Writer() {}
762
763 bool Append(uint8_t*, size_t) { return false; }
764};
765
766TEST(ziparchive, Inflate) {
767 const uint32_t compressed_length = kATxtContentsCompressed.size();
768 const uint32_t uncompressed_length = kATxtContents.size();
769
770 const VectorReader reader(kATxtContentsCompressed);
771 {
772 VectorWriter writer;
773 uint64_t crc_out = 0;
774
775 int32_t ret =
776 zip_archive::Inflate(reader, compressed_length, uncompressed_length, &writer, &crc_out);
777 ASSERT_EQ(0, ret);
778 ASSERT_EQ(kATxtContents, writer.GetOutput());
779 ASSERT_EQ(0x950821C5u, crc_out);
780 }
781
782 {
783 VectorWriter writer;
784 int32_t ret =
785 zip_archive::Inflate(reader, compressed_length, uncompressed_length, &writer, nullptr);
786 ASSERT_EQ(0, ret);
787 ASSERT_EQ(kATxtContents, writer.GetOutput());
788 }
789
790 {
791 BadWriter writer;
792 int32_t ret =
793 zip_archive::Inflate(reader, compressed_length, uncompressed_length, &writer, nullptr);
794 ASSERT_EQ(kIoError, ret);
795 }
796
797 {
798 BadReader reader;
799 VectorWriter writer;
800 int32_t ret =
801 zip_archive::Inflate(reader, compressed_length, uncompressed_length, &writer, nullptr);
802 ASSERT_EQ(kIoError, ret);
803 ASSERT_EQ(0u, writer.GetOutput().size());
804 }
805}
806
Narayan Kamath58aaf462013-12-10 16:47:14 +0000807int main(int argc, char** argv) {
808 ::testing::InitGoogleTest(&argc, argv);
809
Jiyong Parkcd997e62017-06-30 17:23:33 +0900810 static struct option options[] = {{"test_data_dir", required_argument, nullptr, 't'},
811 {nullptr, 0, nullptr, 0}};
Narayan Kamath58aaf462013-12-10 16:47:14 +0000812
813 while (true) {
814 int option_index;
815 const int c = getopt_long_only(argc, argv, "", options, &option_index);
816 if (c == -1) {
817 break;
818 }
819
820 if (c == 't') {
821 test_data_dir = optarg;
822 }
Narayan Kamath7462f022013-11-21 13:05:04 +0000823 }
824
Narayan Kamath58aaf462013-12-10 16:47:14 +0000825 if (test_data_dir.size() == 0) {
826 printf("Test data flag (--test_data_dir) required\n\n");
827 return -1;
828 }
Narayan Kamath7462f022013-11-21 13:05:04 +0000829
Narayan Kamath58aaf462013-12-10 16:47:14 +0000830 if (test_data_dir[0] != '/') {
Christopher Ferrise6884ce2015-11-10 14:55:12 -0800831 std::vector<char> cwd_buffer(1024);
832 const char* cwd = getcwd(cwd_buffer.data(), cwd_buffer.size() - 1);
833 if (cwd == nullptr) {
834 printf("Cannot get current working directory, use an absolute path instead, was %s\n\n",
835 test_data_dir.c_str());
836 return -2;
837 }
838 test_data_dir = '/' + test_data_dir;
839 test_data_dir = cwd + test_data_dir;
Narayan Kamath58aaf462013-12-10 16:47:14 +0000840 }
Narayan Kamath7462f022013-11-21 13:05:04 +0000841
Narayan Kamath58aaf462013-12-10 16:47:14 +0000842 return RUN_ALL_TESTS();
Narayan Kamath7462f022013-11-21 13:05:04 +0000843}