1*adcb0a62SAndroid Build Coastguard Worker /*
2*adcb0a62SAndroid Build Coastguard Worker * Copyright (C) 2013 The Android Open Source Project
3*adcb0a62SAndroid Build Coastguard Worker *
4*adcb0a62SAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*adcb0a62SAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*adcb0a62SAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*adcb0a62SAndroid Build Coastguard Worker *
8*adcb0a62SAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*adcb0a62SAndroid Build Coastguard Worker *
10*adcb0a62SAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*adcb0a62SAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*adcb0a62SAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*adcb0a62SAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*adcb0a62SAndroid Build Coastguard Worker * limitations under the License.
15*adcb0a62SAndroid Build Coastguard Worker */
16*adcb0a62SAndroid Build Coastguard Worker
17*adcb0a62SAndroid Build Coastguard Worker #include <errno.h>
18*adcb0a62SAndroid Build Coastguard Worker #include <fcntl.h>
19*adcb0a62SAndroid Build Coastguard Worker #include <getopt.h>
20*adcb0a62SAndroid Build Coastguard Worker #include <stdio.h>
21*adcb0a62SAndroid Build Coastguard Worker #include <string.h>
22*adcb0a62SAndroid Build Coastguard Worker #include <unistd.h>
23*adcb0a62SAndroid Build Coastguard Worker
24*adcb0a62SAndroid Build Coastguard Worker #include <map>
25*adcb0a62SAndroid Build Coastguard Worker #include <memory>
26*adcb0a62SAndroid Build Coastguard Worker #include <set>
27*adcb0a62SAndroid Build Coastguard Worker #include <string_view>
28*adcb0a62SAndroid Build Coastguard Worker #include <vector>
29*adcb0a62SAndroid Build Coastguard Worker
30*adcb0a62SAndroid Build Coastguard Worker #include <android-base/file.h>
31*adcb0a62SAndroid Build Coastguard Worker #include <android-base/logging.h>
32*adcb0a62SAndroid Build Coastguard Worker #include <android-base/mapped_file.h>
33*adcb0a62SAndroid Build Coastguard Worker #include <android-base/memory.h>
34*adcb0a62SAndroid Build Coastguard Worker #include <android-base/strings.h>
35*adcb0a62SAndroid Build Coastguard Worker #include <android-base/unique_fd.h>
36*adcb0a62SAndroid Build Coastguard Worker #include <gtest/gtest.h>
37*adcb0a62SAndroid Build Coastguard Worker #include <ziparchive/zip_archive.h>
38*adcb0a62SAndroid Build Coastguard Worker #include <ziparchive/zip_archive_stream_entry.h>
39*adcb0a62SAndroid Build Coastguard Worker
40*adcb0a62SAndroid Build Coastguard Worker #include "zip_archive_common.h"
41*adcb0a62SAndroid Build Coastguard Worker #include "zip_archive_private.h"
42*adcb0a62SAndroid Build Coastguard Worker
43*adcb0a62SAndroid Build Coastguard Worker static std::string test_data_dir = android::base::GetExecutableDirectory() + "/testdata";
44*adcb0a62SAndroid Build Coastguard Worker
45*adcb0a62SAndroid Build Coastguard Worker static const std::string kValidZip = "valid.zip";
46*adcb0a62SAndroid Build Coastguard Worker static const std::string kLargeZip = "large.zip";
47*adcb0a62SAndroid Build Coastguard Worker static const std::string kBadCrcZip = "bad_crc.zip";
48*adcb0a62SAndroid Build Coastguard Worker
49*adcb0a62SAndroid Build Coastguard Worker static const std::vector<uint8_t> kATxtContents{'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'a',
50*adcb0a62SAndroid Build Coastguard Worker 'b', 'c', 'd', 'e', 'f', 'g', 'h', '\n'};
51*adcb0a62SAndroid Build Coastguard Worker
52*adcb0a62SAndroid Build Coastguard Worker static const std::vector<uint8_t> kATxtContentsCompressed{'K', 'L', 'J', 'N', 'I', 'M', 'K',
53*adcb0a62SAndroid Build Coastguard Worker 207, 'H', 132, 210, '\\', '\0'};
54*adcb0a62SAndroid Build Coastguard Worker
55*adcb0a62SAndroid Build Coastguard Worker static const std::vector<uint8_t> kBTxtContents{'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', '\n'};
56*adcb0a62SAndroid Build Coastguard Worker
OpenArchiveWrapper(const std::string & name,ZipArchiveHandle * handle)57*adcb0a62SAndroid Build Coastguard Worker static int32_t OpenArchiveWrapper(const std::string& name, ZipArchiveHandle* handle) {
58*adcb0a62SAndroid Build Coastguard Worker const std::string abs_path = test_data_dir + "/" + name;
59*adcb0a62SAndroid Build Coastguard Worker return OpenArchive(abs_path.c_str(), handle);
60*adcb0a62SAndroid Build Coastguard Worker }
61*adcb0a62SAndroid Build Coastguard Worker
62*adcb0a62SAndroid Build Coastguard Worker class CdEntryMapTest : public ::testing::Test {
63*adcb0a62SAndroid Build Coastguard Worker protected:
SetUp()64*adcb0a62SAndroid Build Coastguard Worker void SetUp() override {
65*adcb0a62SAndroid Build Coastguard Worker names_ = {
66*adcb0a62SAndroid Build Coastguard Worker "a.txt", "b.txt", "b/", "b/c.txt", "b/d.txt",
67*adcb0a62SAndroid Build Coastguard Worker };
68*adcb0a62SAndroid Build Coastguard Worker separator_ = "separator";
69*adcb0a62SAndroid Build Coastguard Worker header_ = "metadata";
70*adcb0a62SAndroid Build Coastguard Worker joined_names_ = header_ + android::base::Join(names_, separator_);
71*adcb0a62SAndroid Build Coastguard Worker base_ptr_ = reinterpret_cast<uint8_t*>(&joined_names_[0]);
72*adcb0a62SAndroid Build Coastguard Worker
73*adcb0a62SAndroid Build Coastguard Worker uint16_t num_entries = static_cast<uint16_t>(names_.size());
74*adcb0a62SAndroid Build Coastguard Worker entry_maps_.emplace_back(new CdEntryMapZip32<ZipStringOffset20>(num_entries));
75*adcb0a62SAndroid Build Coastguard Worker entry_maps_.emplace_back(new CdEntryMapZip32<ZipStringOffset32>(num_entries));
76*adcb0a62SAndroid Build Coastguard Worker entry_maps_.emplace_back(new CdEntryMapZip64());
77*adcb0a62SAndroid Build Coastguard Worker for (auto& cd_map : entry_maps_) {
78*adcb0a62SAndroid Build Coastguard Worker ASSERT_NE(nullptr, cd_map);
79*adcb0a62SAndroid Build Coastguard Worker size_t offset = header_.size();
80*adcb0a62SAndroid Build Coastguard Worker for (const auto& name : names_) {
81*adcb0a62SAndroid Build Coastguard Worker auto status = cd_map->AddToMap(
82*adcb0a62SAndroid Build Coastguard Worker std::string_view{joined_names_.c_str() + offset, name.size()}, base_ptr_);
83*adcb0a62SAndroid Build Coastguard Worker ASSERT_EQ(0, status);
84*adcb0a62SAndroid Build Coastguard Worker offset += name.size() + separator_.size();
85*adcb0a62SAndroid Build Coastguard Worker }
86*adcb0a62SAndroid Build Coastguard Worker }
87*adcb0a62SAndroid Build Coastguard Worker }
88*adcb0a62SAndroid Build Coastguard Worker
89*adcb0a62SAndroid Build Coastguard Worker std::vector<std::string> names_;
90*adcb0a62SAndroid Build Coastguard Worker // A continuous region of memory serves as a mock of the central directory.
91*adcb0a62SAndroid Build Coastguard Worker std::string joined_names_;
92*adcb0a62SAndroid Build Coastguard Worker // We expect some metadata at the beginning of the central directory and between filenames.
93*adcb0a62SAndroid Build Coastguard Worker std::string header_;
94*adcb0a62SAndroid Build Coastguard Worker std::string separator_;
95*adcb0a62SAndroid Build Coastguard Worker
96*adcb0a62SAndroid Build Coastguard Worker std::vector<std::unique_ptr<CdEntryMapInterface>> entry_maps_;
97*adcb0a62SAndroid Build Coastguard Worker uint8_t* base_ptr_{nullptr}; // Points to the start of the central directory.
98*adcb0a62SAndroid Build Coastguard Worker };
99*adcb0a62SAndroid Build Coastguard Worker
TEST_F(CdEntryMapTest,AddDuplicatedEntry)100*adcb0a62SAndroid Build Coastguard Worker TEST_F(CdEntryMapTest, AddDuplicatedEntry) {
101*adcb0a62SAndroid Build Coastguard Worker for (auto& cd_map : entry_maps_) {
102*adcb0a62SAndroid Build Coastguard Worker std::string_view name = "b.txt";
103*adcb0a62SAndroid Build Coastguard Worker ASSERT_NE(0, cd_map->AddToMap(name, base_ptr_));
104*adcb0a62SAndroid Build Coastguard Worker }
105*adcb0a62SAndroid Build Coastguard Worker }
106*adcb0a62SAndroid Build Coastguard Worker
TEST_F(CdEntryMapTest,FindEntry)107*adcb0a62SAndroid Build Coastguard Worker TEST_F(CdEntryMapTest, FindEntry) {
108*adcb0a62SAndroid Build Coastguard Worker for (auto& cd_map : entry_maps_) {
109*adcb0a62SAndroid Build Coastguard Worker uint64_t expected_offset = header_.size();
110*adcb0a62SAndroid Build Coastguard Worker for (const auto& name : names_) {
111*adcb0a62SAndroid Build Coastguard Worker auto [status, offset] = cd_map->GetCdEntryOffset(name, base_ptr_);
112*adcb0a62SAndroid Build Coastguard Worker ASSERT_EQ(status, kSuccess);
113*adcb0a62SAndroid Build Coastguard Worker ASSERT_EQ(offset, expected_offset);
114*adcb0a62SAndroid Build Coastguard Worker expected_offset += name.size() + separator_.size();
115*adcb0a62SAndroid Build Coastguard Worker }
116*adcb0a62SAndroid Build Coastguard Worker }
117*adcb0a62SAndroid Build Coastguard Worker }
118*adcb0a62SAndroid Build Coastguard Worker
TEST_F(CdEntryMapTest,Iteration)119*adcb0a62SAndroid Build Coastguard Worker TEST_F(CdEntryMapTest, Iteration) {
120*adcb0a62SAndroid Build Coastguard Worker std::set<std::string_view> expected(names_.begin(), names_.end());
121*adcb0a62SAndroid Build Coastguard Worker for (auto& cd_map : entry_maps_) {
122*adcb0a62SAndroid Build Coastguard Worker cd_map->ResetIteration();
123*adcb0a62SAndroid Build Coastguard Worker std::set<std::string_view> entry_set;
124*adcb0a62SAndroid Build Coastguard Worker auto ret = cd_map->Next(base_ptr_);
125*adcb0a62SAndroid Build Coastguard Worker while (ret != std::pair<std::string_view, uint64_t>{}) {
126*adcb0a62SAndroid Build Coastguard Worker auto [it, insert_status] = entry_set.insert(ret.first);
127*adcb0a62SAndroid Build Coastguard Worker ASSERT_TRUE(insert_status);
128*adcb0a62SAndroid Build Coastguard Worker ret = cd_map->Next(base_ptr_);
129*adcb0a62SAndroid Build Coastguard Worker }
130*adcb0a62SAndroid Build Coastguard Worker ASSERT_EQ(expected, entry_set);
131*adcb0a62SAndroid Build Coastguard Worker }
132*adcb0a62SAndroid Build Coastguard Worker }
133*adcb0a62SAndroid Build Coastguard Worker
TEST(ziparchive,Open)134*adcb0a62SAndroid Build Coastguard Worker TEST(ziparchive, Open) {
135*adcb0a62SAndroid Build Coastguard Worker ZipArchiveHandle handle;
136*adcb0a62SAndroid Build Coastguard Worker ASSERT_EQ(0, OpenArchiveWrapper(kValidZip, &handle));
137*adcb0a62SAndroid Build Coastguard Worker // TODO(b/287285733): restore mmap() when the cold cache regression is fixed.
138*adcb0a62SAndroid Build Coastguard Worker #if 0
139*adcb0a62SAndroid Build Coastguard Worker const auto& mappedFile = handle->mapped_zip;
140*adcb0a62SAndroid Build Coastguard Worker if constexpr (sizeof(void*) < 8) {
141*adcb0a62SAndroid Build Coastguard Worker ASSERT_EQ(nullptr, mappedFile.GetBasePtr());
142*adcb0a62SAndroid Build Coastguard Worker } else {
143*adcb0a62SAndroid Build Coastguard Worker ASSERT_NE(nullptr, mappedFile.GetBasePtr());
144*adcb0a62SAndroid Build Coastguard Worker }
145*adcb0a62SAndroid Build Coastguard Worker #endif // 0
146*adcb0a62SAndroid Build Coastguard Worker CloseArchive(handle);
147*adcb0a62SAndroid Build Coastguard Worker ASSERT_EQ(kInvalidEntryName, OpenArchiveWrapper("bad_filename.zip", &handle));
148*adcb0a62SAndroid Build Coastguard Worker CloseArchive(handle);
149*adcb0a62SAndroid Build Coastguard Worker }
150*adcb0a62SAndroid Build Coastguard Worker
TEST(ziparchive,OutOfBound)151*adcb0a62SAndroid Build Coastguard Worker TEST(ziparchive, OutOfBound) {
152*adcb0a62SAndroid Build Coastguard Worker ZipArchiveHandle handle;
153*adcb0a62SAndroid Build Coastguard Worker ASSERT_EQ(kInvalidOffset, OpenArchiveWrapper("crash.apk", &handle));
154*adcb0a62SAndroid Build Coastguard Worker CloseArchive(handle);
155*adcb0a62SAndroid Build Coastguard Worker }
156*adcb0a62SAndroid Build Coastguard Worker
TEST(ziparchive,EmptyArchive)157*adcb0a62SAndroid Build Coastguard Worker TEST(ziparchive, EmptyArchive) {
158*adcb0a62SAndroid Build Coastguard Worker ZipArchiveHandle handle;
159*adcb0a62SAndroid Build Coastguard Worker ASSERT_EQ(kEmptyArchive, OpenArchiveWrapper("empty.zip", &handle));
160*adcb0a62SAndroid Build Coastguard Worker CloseArchive(handle);
161*adcb0a62SAndroid Build Coastguard Worker }
162*adcb0a62SAndroid Build Coastguard Worker
TEST(ziparchive,ZeroSizeCentralDirectory)163*adcb0a62SAndroid Build Coastguard Worker TEST(ziparchive, ZeroSizeCentralDirectory) {
164*adcb0a62SAndroid Build Coastguard Worker ZipArchiveHandle handle;
165*adcb0a62SAndroid Build Coastguard Worker ASSERT_EQ(kInvalidFile, OpenArchiveWrapper("zero-size-cd.zip", &handle));
166*adcb0a62SAndroid Build Coastguard Worker CloseArchive(handle);
167*adcb0a62SAndroid Build Coastguard Worker }
168*adcb0a62SAndroid Build Coastguard Worker
TEST(ziparchive,OpenMissing)169*adcb0a62SAndroid Build Coastguard Worker TEST(ziparchive, OpenMissing) {
170*adcb0a62SAndroid Build Coastguard Worker ZipArchiveHandle handle;
171*adcb0a62SAndroid Build Coastguard Worker ASSERT_NE(0, OpenArchiveWrapper("missing.zip", &handle));
172*adcb0a62SAndroid Build Coastguard Worker
173*adcb0a62SAndroid Build Coastguard Worker // Confirm the file descriptor is not going to be mistaken for a valid one.
174*adcb0a62SAndroid Build Coastguard Worker ASSERT_EQ(-1, GetFileDescriptor(handle));
175*adcb0a62SAndroid Build Coastguard Worker }
176*adcb0a62SAndroid Build Coastguard Worker
TEST(ziparchive,OpenAssumeFdOwnership)177*adcb0a62SAndroid Build Coastguard Worker TEST(ziparchive, OpenAssumeFdOwnership) {
178*adcb0a62SAndroid Build Coastguard Worker int fd = open((test_data_dir + "/" + kValidZip).c_str(), O_RDONLY | O_BINARY);
179*adcb0a62SAndroid Build Coastguard Worker ASSERT_NE(-1, fd);
180*adcb0a62SAndroid Build Coastguard Worker ZipArchiveHandle handle;
181*adcb0a62SAndroid Build Coastguard Worker ASSERT_EQ(0, OpenArchiveFd(fd, "OpenWithAssumeFdOwnership", &handle));
182*adcb0a62SAndroid Build Coastguard Worker CloseArchive(handle);
183*adcb0a62SAndroid Build Coastguard Worker ASSERT_EQ(-1, lseek(fd, 0, SEEK_SET));
184*adcb0a62SAndroid Build Coastguard Worker ASSERT_EQ(EBADF, errno);
185*adcb0a62SAndroid Build Coastguard Worker }
186*adcb0a62SAndroid Build Coastguard Worker
TEST(ziparchive,OpenDoNotAssumeFdOwnership)187*adcb0a62SAndroid Build Coastguard Worker TEST(ziparchive, OpenDoNotAssumeFdOwnership) {
188*adcb0a62SAndroid Build Coastguard Worker int fd = open((test_data_dir + "/" + kValidZip).c_str(), O_RDONLY | O_BINARY);
189*adcb0a62SAndroid Build Coastguard Worker ASSERT_NE(-1, fd);
190*adcb0a62SAndroid Build Coastguard Worker ZipArchiveHandle handle;
191*adcb0a62SAndroid Build Coastguard Worker ASSERT_EQ(0, OpenArchiveFd(fd, "OpenWithAssumeFdOwnership", &handle, false));
192*adcb0a62SAndroid Build Coastguard Worker CloseArchive(handle);
193*adcb0a62SAndroid Build Coastguard Worker ASSERT_EQ(0, lseek(fd, 0, SEEK_SET));
194*adcb0a62SAndroid Build Coastguard Worker close(fd);
195*adcb0a62SAndroid Build Coastguard Worker }
196*adcb0a62SAndroid Build Coastguard Worker
TEST(ziparchive,OpenAssumeFdRangeOwnership)197*adcb0a62SAndroid Build Coastguard Worker TEST(ziparchive, OpenAssumeFdRangeOwnership) {
198*adcb0a62SAndroid Build Coastguard Worker int fd = open((test_data_dir + "/" + kValidZip).c_str(), O_RDONLY | O_BINARY);
199*adcb0a62SAndroid Build Coastguard Worker ASSERT_NE(-1, fd);
200*adcb0a62SAndroid Build Coastguard Worker const off64_t length = lseek64(fd, 0, SEEK_END);
201*adcb0a62SAndroid Build Coastguard Worker ASSERT_NE(-1, length);
202*adcb0a62SAndroid Build Coastguard Worker ZipArchiveHandle handle;
203*adcb0a62SAndroid Build Coastguard Worker ASSERT_EQ(0, OpenArchiveFdRange(fd, "OpenWithAssumeFdOwnership", &handle,
204*adcb0a62SAndroid Build Coastguard Worker static_cast<size_t>(length), 0));
205*adcb0a62SAndroid Build Coastguard Worker CloseArchive(handle);
206*adcb0a62SAndroid Build Coastguard Worker ASSERT_EQ(-1, lseek(fd, 0, SEEK_SET));
207*adcb0a62SAndroid Build Coastguard Worker ASSERT_EQ(EBADF, errno);
208*adcb0a62SAndroid Build Coastguard Worker }
209*adcb0a62SAndroid Build Coastguard Worker
TEST(ziparchive,OpenDoNotAssumeFdRangeOwnership)210*adcb0a62SAndroid Build Coastguard Worker TEST(ziparchive, OpenDoNotAssumeFdRangeOwnership) {
211*adcb0a62SAndroid Build Coastguard Worker int fd = open((test_data_dir + "/" + kValidZip).c_str(), O_RDONLY | O_BINARY);
212*adcb0a62SAndroid Build Coastguard Worker ASSERT_NE(-1, fd);
213*adcb0a62SAndroid Build Coastguard Worker const off64_t length = lseek(fd, 0, SEEK_END);
214*adcb0a62SAndroid Build Coastguard Worker ASSERT_NE(-1, length);
215*adcb0a62SAndroid Build Coastguard Worker ZipArchiveHandle handle;
216*adcb0a62SAndroid Build Coastguard Worker ASSERT_EQ(0, OpenArchiveFdRange(fd, "OpenWithAssumeFdOwnership", &handle,
217*adcb0a62SAndroid Build Coastguard Worker static_cast<size_t>(length), 0, false));
218*adcb0a62SAndroid Build Coastguard Worker CloseArchive(handle);
219*adcb0a62SAndroid Build Coastguard Worker ASSERT_EQ(0, lseek(fd, 0, SEEK_SET));
220*adcb0a62SAndroid Build Coastguard Worker close(fd);
221*adcb0a62SAndroid Build Coastguard Worker }
222*adcb0a62SAndroid Build Coastguard Worker
TEST(ziparchive,Iteration_std_string_view)223*adcb0a62SAndroid Build Coastguard Worker TEST(ziparchive, Iteration_std_string_view) {
224*adcb0a62SAndroid Build Coastguard Worker ZipArchiveHandle handle;
225*adcb0a62SAndroid Build Coastguard Worker ASSERT_EQ(0, OpenArchiveWrapper(kValidZip, &handle));
226*adcb0a62SAndroid Build Coastguard Worker
227*adcb0a62SAndroid Build Coastguard Worker void* iteration_cookie;
228*adcb0a62SAndroid Build Coastguard Worker ASSERT_EQ(0, StartIteration(handle, &iteration_cookie));
229*adcb0a62SAndroid Build Coastguard Worker
230*adcb0a62SAndroid Build Coastguard Worker ZipEntry64 data;
231*adcb0a62SAndroid Build Coastguard Worker std::vector<std::string_view> names;
232*adcb0a62SAndroid Build Coastguard Worker std::string_view name;
233*adcb0a62SAndroid Build Coastguard Worker while (Next(iteration_cookie, &data, &name) == 0) names.push_back(name);
234*adcb0a62SAndroid Build Coastguard Worker
235*adcb0a62SAndroid Build Coastguard Worker // Assert that the names are as expected.
236*adcb0a62SAndroid Build Coastguard Worker std::vector<std::string_view> expected_names{"a.txt", "b.txt", "b/", "b/c.txt", "b/d.txt"};
237*adcb0a62SAndroid Build Coastguard Worker std::sort(names.begin(), names.end());
238*adcb0a62SAndroid Build Coastguard Worker ASSERT_EQ(expected_names, names);
239*adcb0a62SAndroid Build Coastguard Worker
240*adcb0a62SAndroid Build Coastguard Worker CloseArchive(handle);
241*adcb0a62SAndroid Build Coastguard Worker }
242*adcb0a62SAndroid Build Coastguard Worker
AssertIterationNames(void * iteration_cookie,const std::vector<std::string> & expected_names_sorted)243*adcb0a62SAndroid Build Coastguard Worker static void AssertIterationNames(void* iteration_cookie,
244*adcb0a62SAndroid Build Coastguard Worker const std::vector<std::string>& expected_names_sorted) {
245*adcb0a62SAndroid Build Coastguard Worker ZipEntry64 data;
246*adcb0a62SAndroid Build Coastguard Worker std::vector<std::string> names;
247*adcb0a62SAndroid Build Coastguard Worker std::string_view name;
248*adcb0a62SAndroid Build Coastguard Worker for (size_t i = 0; i < expected_names_sorted.size(); ++i) {
249*adcb0a62SAndroid Build Coastguard Worker ASSERT_EQ(0, Next(iteration_cookie, &data, &name));
250*adcb0a62SAndroid Build Coastguard Worker names.push_back(std::string(name));
251*adcb0a62SAndroid Build Coastguard Worker }
252*adcb0a62SAndroid Build Coastguard Worker // End of iteration.
253*adcb0a62SAndroid Build Coastguard Worker ASSERT_EQ(-1, Next(iteration_cookie, &data, &name));
254*adcb0a62SAndroid Build Coastguard Worker // Assert that the names are as expected.
255*adcb0a62SAndroid Build Coastguard Worker std::sort(names.begin(), names.end());
256*adcb0a62SAndroid Build Coastguard Worker ASSERT_EQ(expected_names_sorted, names);
257*adcb0a62SAndroid Build Coastguard Worker }
258*adcb0a62SAndroid Build Coastguard Worker
AssertIterationOrder(const std::string_view prefix,const std::string_view suffix,const std::vector<std::string> & expected_names_sorted)259*adcb0a62SAndroid Build Coastguard Worker static void AssertIterationOrder(const std::string_view prefix, const std::string_view suffix,
260*adcb0a62SAndroid Build Coastguard Worker const std::vector<std::string>& expected_names_sorted) {
261*adcb0a62SAndroid Build Coastguard Worker ZipArchiveHandle handle;
262*adcb0a62SAndroid Build Coastguard Worker ASSERT_EQ(0, OpenArchiveWrapper(kValidZip, &handle));
263*adcb0a62SAndroid Build Coastguard Worker
264*adcb0a62SAndroid Build Coastguard Worker void* iteration_cookie;
265*adcb0a62SAndroid Build Coastguard Worker ASSERT_EQ(0, StartIteration(handle, &iteration_cookie, prefix, suffix));
266*adcb0a62SAndroid Build Coastguard Worker AssertIterationNames(iteration_cookie, expected_names_sorted);
267*adcb0a62SAndroid Build Coastguard Worker CloseArchive(handle);
268*adcb0a62SAndroid Build Coastguard Worker }
269*adcb0a62SAndroid Build Coastguard Worker
AssertIterationOrderWithMatcher(std::function<bool (std::string_view)> matcher,const std::vector<std::string> & expected_names_sorted)270*adcb0a62SAndroid Build Coastguard Worker static void AssertIterationOrderWithMatcher(std::function<bool(std::string_view)> matcher,
271*adcb0a62SAndroid Build Coastguard Worker const std::vector<std::string>& expected_names_sorted) {
272*adcb0a62SAndroid Build Coastguard Worker ZipArchiveHandle handle;
273*adcb0a62SAndroid Build Coastguard Worker ASSERT_EQ(0, OpenArchiveWrapper(kValidZip, &handle));
274*adcb0a62SAndroid Build Coastguard Worker
275*adcb0a62SAndroid Build Coastguard Worker void* iteration_cookie;
276*adcb0a62SAndroid Build Coastguard Worker ASSERT_EQ(0, StartIteration(handle, &iteration_cookie, matcher));
277*adcb0a62SAndroid Build Coastguard Worker AssertIterationNames(iteration_cookie, expected_names_sorted);
278*adcb0a62SAndroid Build Coastguard Worker CloseArchive(handle);
279*adcb0a62SAndroid Build Coastguard Worker }
280*adcb0a62SAndroid Build Coastguard Worker
TEST(ziparchive,Iteration)281*adcb0a62SAndroid Build Coastguard Worker TEST(ziparchive, Iteration) {
282*adcb0a62SAndroid Build Coastguard Worker static const std::vector<std::string> kExpectedMatchesSorted = {"a.txt", "b.txt", "b/", "b/c.txt",
283*adcb0a62SAndroid Build Coastguard Worker "b/d.txt"};
284*adcb0a62SAndroid Build Coastguard Worker
285*adcb0a62SAndroid Build Coastguard Worker AssertIterationOrder("", "", kExpectedMatchesSorted);
286*adcb0a62SAndroid Build Coastguard Worker }
287*adcb0a62SAndroid Build Coastguard Worker
TEST(ziparchive,IterationWithPrefix)288*adcb0a62SAndroid Build Coastguard Worker TEST(ziparchive, IterationWithPrefix) {
289*adcb0a62SAndroid Build Coastguard Worker static const std::vector<std::string> kExpectedMatchesSorted = {"b/", "b/c.txt", "b/d.txt"};
290*adcb0a62SAndroid Build Coastguard Worker
291*adcb0a62SAndroid Build Coastguard Worker AssertIterationOrder("b/", "", kExpectedMatchesSorted);
292*adcb0a62SAndroid Build Coastguard Worker }
293*adcb0a62SAndroid Build Coastguard Worker
TEST(ziparchive,IterationWithSuffix)294*adcb0a62SAndroid Build Coastguard Worker TEST(ziparchive, IterationWithSuffix) {
295*adcb0a62SAndroid Build Coastguard Worker static const std::vector<std::string> kExpectedMatchesSorted = {"a.txt", "b.txt", "b/c.txt",
296*adcb0a62SAndroid Build Coastguard Worker "b/d.txt"};
297*adcb0a62SAndroid Build Coastguard Worker
298*adcb0a62SAndroid Build Coastguard Worker AssertIterationOrder("", ".txt", kExpectedMatchesSorted);
299*adcb0a62SAndroid Build Coastguard Worker }
300*adcb0a62SAndroid Build Coastguard Worker
TEST(ziparchive,IterationWithPrefixAndSuffix)301*adcb0a62SAndroid Build Coastguard Worker TEST(ziparchive, IterationWithPrefixAndSuffix) {
302*adcb0a62SAndroid Build Coastguard Worker static const std::vector<std::string> kExpectedMatchesSorted = {"b.txt", "b/c.txt", "b/d.txt"};
303*adcb0a62SAndroid Build Coastguard Worker
304*adcb0a62SAndroid Build Coastguard Worker AssertIterationOrder("b", ".txt", kExpectedMatchesSorted);
305*adcb0a62SAndroid Build Coastguard Worker }
306*adcb0a62SAndroid Build Coastguard Worker
TEST(ziparchive,IterationWithAdditionalMatchesExactly)307*adcb0a62SAndroid Build Coastguard Worker TEST(ziparchive, IterationWithAdditionalMatchesExactly) {
308*adcb0a62SAndroid Build Coastguard Worker static const std::vector<std::string> kExpectedMatchesSorted = {"a.txt"};
309*adcb0a62SAndroid Build Coastguard Worker auto matcher = [](std::string_view name) { return name == "a.txt"; };
310*adcb0a62SAndroid Build Coastguard Worker AssertIterationOrderWithMatcher(matcher, kExpectedMatchesSorted);
311*adcb0a62SAndroid Build Coastguard Worker }
312*adcb0a62SAndroid Build Coastguard Worker
TEST(ziparchive,IterationWithAdditionalMatchesWithSuffix)313*adcb0a62SAndroid Build Coastguard Worker TEST(ziparchive, IterationWithAdditionalMatchesWithSuffix) {
314*adcb0a62SAndroid Build Coastguard Worker static const std::vector<std::string> kExpectedMatchesSorted = {"a.txt", "b.txt", "b/c.txt",
315*adcb0a62SAndroid Build Coastguard Worker "b/d.txt"};
316*adcb0a62SAndroid Build Coastguard Worker auto matcher = [](std::string_view name) {
317*adcb0a62SAndroid Build Coastguard Worker return name == "a.txt" || android::base::EndsWith(name, ".txt");
318*adcb0a62SAndroid Build Coastguard Worker };
319*adcb0a62SAndroid Build Coastguard Worker AssertIterationOrderWithMatcher(matcher, kExpectedMatchesSorted);
320*adcb0a62SAndroid Build Coastguard Worker }
321*adcb0a62SAndroid Build Coastguard Worker
TEST(ziparchive,IterationWithAdditionalMatchesWithPrefixAndSuffix)322*adcb0a62SAndroid Build Coastguard Worker TEST(ziparchive, IterationWithAdditionalMatchesWithPrefixAndSuffix) {
323*adcb0a62SAndroid Build Coastguard Worker static const std::vector<std::string> kExpectedMatchesSorted = {"a.txt", "b/c.txt", "b/d.txt"};
324*adcb0a62SAndroid Build Coastguard Worker auto matcher = [](std::string_view name) {
325*adcb0a62SAndroid Build Coastguard Worker return name == "a.txt" ||
326*adcb0a62SAndroid Build Coastguard Worker (android::base::EndsWith(name, ".txt") && android::base::StartsWith(name, "b/"));
327*adcb0a62SAndroid Build Coastguard Worker };
328*adcb0a62SAndroid Build Coastguard Worker AssertIterationOrderWithMatcher(matcher, kExpectedMatchesSorted);
329*adcb0a62SAndroid Build Coastguard Worker }
330*adcb0a62SAndroid Build Coastguard Worker
TEST(ziparchive,IterationWithBadPrefixAndSuffix)331*adcb0a62SAndroid Build Coastguard Worker TEST(ziparchive, IterationWithBadPrefixAndSuffix) {
332*adcb0a62SAndroid Build Coastguard Worker ZipArchiveHandle handle;
333*adcb0a62SAndroid Build Coastguard Worker ASSERT_EQ(0, OpenArchiveWrapper(kValidZip, &handle));
334*adcb0a62SAndroid Build Coastguard Worker
335*adcb0a62SAndroid Build Coastguard Worker void* iteration_cookie;
336*adcb0a62SAndroid Build Coastguard Worker ASSERT_EQ(0, StartIteration(handle, &iteration_cookie, "x", "y"));
337*adcb0a62SAndroid Build Coastguard Worker
338*adcb0a62SAndroid Build Coastguard Worker ZipEntry64 data;
339*adcb0a62SAndroid Build Coastguard Worker std::string_view name;
340*adcb0a62SAndroid Build Coastguard Worker
341*adcb0a62SAndroid Build Coastguard Worker // End of iteration.
342*adcb0a62SAndroid Build Coastguard Worker ASSERT_EQ(-1, Next(iteration_cookie, &data, &name));
343*adcb0a62SAndroid Build Coastguard Worker
344*adcb0a62SAndroid Build Coastguard Worker CloseArchive(handle);
345*adcb0a62SAndroid Build Coastguard Worker }
346*adcb0a62SAndroid Build Coastguard Worker
TEST(ziparchive,FindEntry)347*adcb0a62SAndroid Build Coastguard Worker TEST(ziparchive, FindEntry) {
348*adcb0a62SAndroid Build Coastguard Worker ZipArchiveHandle handle;
349*adcb0a62SAndroid Build Coastguard Worker ASSERT_EQ(0, OpenArchiveWrapper(kValidZip, &handle));
350*adcb0a62SAndroid Build Coastguard Worker
351*adcb0a62SAndroid Build Coastguard Worker ZipEntry64 data;
352*adcb0a62SAndroid Build Coastguard Worker ASSERT_EQ(0, FindEntry(handle, "a.txt", &data));
353*adcb0a62SAndroid Build Coastguard Worker
354*adcb0a62SAndroid Build Coastguard Worker // Known facts about a.txt, from zipinfo -v.
355*adcb0a62SAndroid Build Coastguard Worker ASSERT_EQ(63, data.offset);
356*adcb0a62SAndroid Build Coastguard Worker ASSERT_EQ(kCompressDeflated, data.method);
357*adcb0a62SAndroid Build Coastguard Worker ASSERT_EQ(17u, data.uncompressed_length);
358*adcb0a62SAndroid Build Coastguard Worker ASSERT_EQ(13u, data.compressed_length);
359*adcb0a62SAndroid Build Coastguard Worker ASSERT_EQ(0x950821c5, data.crc32);
360*adcb0a62SAndroid Build Coastguard Worker ASSERT_EQ(static_cast<uint32_t>(0x438a8005), data.mod_time);
361*adcb0a62SAndroid Build Coastguard Worker
362*adcb0a62SAndroid Build Coastguard Worker // size of extra field in local file header confirmed with zipdetails.
363*adcb0a62SAndroid Build Coastguard Worker // zipinfo -v will provide size of extra field from central directory.
364*adcb0a62SAndroid Build Coastguard Worker ASSERT_EQ(28, data.extra_field_size);
365*adcb0a62SAndroid Build Coastguard Worker
366*adcb0a62SAndroid Build Coastguard Worker // An entry that doesn't exist. Should be a negative return code.
367*adcb0a62SAndroid Build Coastguard Worker ASSERT_LT(FindEntry(handle, "this file does not exist", &data), 0);
368*adcb0a62SAndroid Build Coastguard Worker
369*adcb0a62SAndroid Build Coastguard Worker CloseArchive(handle);
370*adcb0a62SAndroid Build Coastguard Worker }
371*adcb0a62SAndroid Build Coastguard Worker
TEST(ziparchive,FindEntry_empty)372*adcb0a62SAndroid Build Coastguard Worker TEST(ziparchive, FindEntry_empty) {
373*adcb0a62SAndroid Build Coastguard Worker ZipArchiveHandle handle;
374*adcb0a62SAndroid Build Coastguard Worker ASSERT_EQ(0, OpenArchiveWrapper(kValidZip, &handle));
375*adcb0a62SAndroid Build Coastguard Worker
376*adcb0a62SAndroid Build Coastguard Worker ZipEntry64 data;
377*adcb0a62SAndroid Build Coastguard Worker ASSERT_EQ(kInvalidEntryName, FindEntry(handle, "", &data));
378*adcb0a62SAndroid Build Coastguard Worker
379*adcb0a62SAndroid Build Coastguard Worker CloseArchive(handle);
380*adcb0a62SAndroid Build Coastguard Worker }
381*adcb0a62SAndroid Build Coastguard Worker
TEST(ziparchive,FindEntry_too_long)382*adcb0a62SAndroid Build Coastguard Worker TEST(ziparchive, FindEntry_too_long) {
383*adcb0a62SAndroid Build Coastguard Worker ZipArchiveHandle handle;
384*adcb0a62SAndroid Build Coastguard Worker ASSERT_EQ(0, OpenArchiveWrapper(kValidZip, &handle));
385*adcb0a62SAndroid Build Coastguard Worker
386*adcb0a62SAndroid Build Coastguard Worker std::string very_long_name(65536, 'x');
387*adcb0a62SAndroid Build Coastguard Worker ZipEntry64 data;
388*adcb0a62SAndroid Build Coastguard Worker ASSERT_EQ(kInvalidEntryName, FindEntry(handle, very_long_name, &data));
389*adcb0a62SAndroid Build Coastguard Worker
390*adcb0a62SAndroid Build Coastguard Worker CloseArchive(handle);
391*adcb0a62SAndroid Build Coastguard Worker }
392*adcb0a62SAndroid Build Coastguard Worker
TEST(ziparchive,TestInvalidDeclaredLength)393*adcb0a62SAndroid Build Coastguard Worker TEST(ziparchive, TestInvalidDeclaredLength) {
394*adcb0a62SAndroid Build Coastguard Worker ZipArchiveHandle handle;
395*adcb0a62SAndroid Build Coastguard Worker ASSERT_EQ(0, OpenArchiveWrapper("declaredlength.zip", &handle));
396*adcb0a62SAndroid Build Coastguard Worker
397*adcb0a62SAndroid Build Coastguard Worker void* iteration_cookie;
398*adcb0a62SAndroid Build Coastguard Worker ASSERT_EQ(0, StartIteration(handle, &iteration_cookie));
399*adcb0a62SAndroid Build Coastguard Worker
400*adcb0a62SAndroid Build Coastguard Worker std::string_view name;
401*adcb0a62SAndroid Build Coastguard Worker ZipEntry64 data;
402*adcb0a62SAndroid Build Coastguard Worker
403*adcb0a62SAndroid Build Coastguard Worker ASSERT_EQ(Next(iteration_cookie, &data, &name), 0);
404*adcb0a62SAndroid Build Coastguard Worker ASSERT_EQ(Next(iteration_cookie, &data, &name), 0);
405*adcb0a62SAndroid Build Coastguard Worker
406*adcb0a62SAndroid Build Coastguard Worker CloseArchive(handle);
407*adcb0a62SAndroid Build Coastguard Worker }
408*adcb0a62SAndroid Build Coastguard Worker
TEST(ziparchive,OpenArchiveFdRange)409*adcb0a62SAndroid Build Coastguard Worker TEST(ziparchive, OpenArchiveFdRange) {
410*adcb0a62SAndroid Build Coastguard Worker TemporaryFile tmp_file;
411*adcb0a62SAndroid Build Coastguard Worker ASSERT_NE(-1, tmp_file.fd);
412*adcb0a62SAndroid Build Coastguard Worker
413*adcb0a62SAndroid Build Coastguard Worker const std::string leading_garbage(21, 'x');
414*adcb0a62SAndroid Build Coastguard Worker ASSERT_TRUE(android::base::WriteFully(tmp_file.fd, leading_garbage.c_str(),
415*adcb0a62SAndroid Build Coastguard Worker leading_garbage.size()));
416*adcb0a62SAndroid Build Coastguard Worker
417*adcb0a62SAndroid Build Coastguard Worker std::string valid_content;
418*adcb0a62SAndroid Build Coastguard Worker ASSERT_TRUE(android::base::ReadFileToString(test_data_dir + "/" + kValidZip, &valid_content));
419*adcb0a62SAndroid Build Coastguard Worker ASSERT_TRUE(android::base::WriteFully(tmp_file.fd, valid_content.c_str(), valid_content.size()));
420*adcb0a62SAndroid Build Coastguard Worker
421*adcb0a62SAndroid Build Coastguard Worker const std::string ending_garbage(42, 'x');
422*adcb0a62SAndroid Build Coastguard Worker ASSERT_TRUE(android::base::WriteFully(tmp_file.fd, ending_garbage.c_str(),
423*adcb0a62SAndroid Build Coastguard Worker ending_garbage.size()));
424*adcb0a62SAndroid Build Coastguard Worker
425*adcb0a62SAndroid Build Coastguard Worker ZipArchiveHandle handle;
426*adcb0a62SAndroid Build Coastguard Worker ASSERT_EQ(0, lseek(tmp_file.fd, 0, SEEK_SET));
427*adcb0a62SAndroid Build Coastguard Worker ASSERT_EQ(0, OpenArchiveFdRange(tmp_file.fd, "OpenArchiveFdRange", &handle,
428*adcb0a62SAndroid Build Coastguard Worker valid_content.size(),
429*adcb0a62SAndroid Build Coastguard Worker static_cast<off64_t>(leading_garbage.size())));
430*adcb0a62SAndroid Build Coastguard Worker
431*adcb0a62SAndroid Build Coastguard Worker // An entry that's deflated.
432*adcb0a62SAndroid Build Coastguard Worker ZipEntry64 data;
433*adcb0a62SAndroid Build Coastguard Worker ASSERT_EQ(0, FindEntry(handle, "a.txt", &data));
434*adcb0a62SAndroid Build Coastguard Worker const auto a_size = static_cast<size_t>(data.uncompressed_length);
435*adcb0a62SAndroid Build Coastguard Worker ASSERT_EQ(a_size, kATxtContents.size());
436*adcb0a62SAndroid Build Coastguard Worker auto buffer = std::unique_ptr<uint8_t[]>(new uint8_t[a_size]);
437*adcb0a62SAndroid Build Coastguard Worker ASSERT_EQ(0, ExtractToMemory(handle, &data, buffer.get(), a_size));
438*adcb0a62SAndroid Build Coastguard Worker ASSERT_EQ(0, memcmp(buffer.get(), kATxtContents.data(), a_size));
439*adcb0a62SAndroid Build Coastguard Worker
440*adcb0a62SAndroid Build Coastguard Worker // An entry that's stored.
441*adcb0a62SAndroid Build Coastguard Worker ASSERT_EQ(0, FindEntry(handle, "b.txt", &data));
442*adcb0a62SAndroid Build Coastguard Worker const auto b_size = static_cast<size_t>(data.uncompressed_length);
443*adcb0a62SAndroid Build Coastguard Worker ASSERT_EQ(b_size, kBTxtContents.size());
444*adcb0a62SAndroid Build Coastguard Worker buffer = std::unique_ptr<uint8_t[]>(new uint8_t[b_size]);
445*adcb0a62SAndroid Build Coastguard Worker ASSERT_EQ(0, ExtractToMemory(handle, &data, buffer.get(), b_size));
446*adcb0a62SAndroid Build Coastguard Worker ASSERT_EQ(0, memcmp(buffer.get(), kBTxtContents.data(), b_size));
447*adcb0a62SAndroid Build Coastguard Worker
448*adcb0a62SAndroid Build Coastguard Worker CloseArchive(handle);
449*adcb0a62SAndroid Build Coastguard Worker }
450*adcb0a62SAndroid Build Coastguard Worker
TEST(ziparchive,ExtractToMemory)451*adcb0a62SAndroid Build Coastguard Worker TEST(ziparchive, ExtractToMemory) {
452*adcb0a62SAndroid Build Coastguard Worker ZipArchiveHandle handle;
453*adcb0a62SAndroid Build Coastguard Worker ASSERT_EQ(0, OpenArchiveWrapper(kValidZip, &handle));
454*adcb0a62SAndroid Build Coastguard Worker
455*adcb0a62SAndroid Build Coastguard Worker // An entry that's deflated.
456*adcb0a62SAndroid Build Coastguard Worker ZipEntry64 data;
457*adcb0a62SAndroid Build Coastguard Worker ASSERT_EQ(0, FindEntry(handle, "a.txt", &data));
458*adcb0a62SAndroid Build Coastguard Worker const auto a_size = static_cast<size_t>(data.uncompressed_length);
459*adcb0a62SAndroid Build Coastguard Worker ASSERT_EQ(a_size, kATxtContents.size());
460*adcb0a62SAndroid Build Coastguard Worker uint8_t* buffer = new uint8_t[a_size];
461*adcb0a62SAndroid Build Coastguard Worker ASSERT_EQ(0, ExtractToMemory(handle, &data, buffer, a_size));
462*adcb0a62SAndroid Build Coastguard Worker ASSERT_EQ(0, memcmp(buffer, kATxtContents.data(), a_size));
463*adcb0a62SAndroid Build Coastguard Worker delete[] buffer;
464*adcb0a62SAndroid Build Coastguard Worker
465*adcb0a62SAndroid Build Coastguard Worker // An entry that's stored.
466*adcb0a62SAndroid Build Coastguard Worker ASSERT_EQ(0, FindEntry(handle, "b.txt", &data));
467*adcb0a62SAndroid Build Coastguard Worker const auto b_size = static_cast<size_t>(data.uncompressed_length);
468*adcb0a62SAndroid Build Coastguard Worker ASSERT_EQ(b_size, kBTxtContents.size());
469*adcb0a62SAndroid Build Coastguard Worker buffer = new uint8_t[b_size];
470*adcb0a62SAndroid Build Coastguard Worker ASSERT_EQ(0, ExtractToMemory(handle, &data, buffer, b_size));
471*adcb0a62SAndroid Build Coastguard Worker ASSERT_EQ(0, memcmp(buffer, kBTxtContents.data(), b_size));
472*adcb0a62SAndroid Build Coastguard Worker delete[] buffer;
473*adcb0a62SAndroid Build Coastguard Worker
474*adcb0a62SAndroid Build Coastguard Worker CloseArchive(handle);
475*adcb0a62SAndroid Build Coastguard Worker }
476*adcb0a62SAndroid Build Coastguard Worker
477*adcb0a62SAndroid Build Coastguard Worker static const uint32_t kEmptyEntriesZip[] = {
478*adcb0a62SAndroid Build Coastguard Worker 0x04034b50, 0x0000000a, 0x63600000, 0x00004438, 0x00000000, 0x00000000, 0x00090000,
479*adcb0a62SAndroid Build Coastguard Worker 0x6d65001c, 0x2e797470, 0x55747874, 0x03000954, 0x52e25c13, 0x52e25c24, 0x000b7875,
480*adcb0a62SAndroid Build Coastguard Worker 0x42890401, 0x88040000, 0x50000013, 0x1e02014b, 0x00000a03, 0x60000000, 0x00443863,
481*adcb0a62SAndroid Build Coastguard Worker 0x00000000, 0x00000000, 0x09000000, 0x00001800, 0x00000000, 0xa0000000, 0x00000081,
482*adcb0a62SAndroid Build Coastguard Worker 0x706d6500, 0x742e7974, 0x54557478, 0x13030005, 0x7552e25c, 0x01000b78, 0x00428904,
483*adcb0a62SAndroid Build Coastguard Worker 0x13880400, 0x4b500000, 0x00000605, 0x00010000, 0x004f0001, 0x00430000, 0x00000000};
484*adcb0a62SAndroid Build Coastguard Worker
485*adcb0a62SAndroid Build Coastguard Worker // This is a zip file containing a single entry (ab.txt) that contains
486*adcb0a62SAndroid Build Coastguard Worker // 90072 repetitions of the string "ab\n" and has an uncompressed length
487*adcb0a62SAndroid Build Coastguard Worker // of 270216 bytes.
488*adcb0a62SAndroid Build Coastguard Worker static const uint16_t kAbZip[] = {
489*adcb0a62SAndroid Build Coastguard Worker 0x4b50, 0x0403, 0x0014, 0x0000, 0x0008, 0x51d2, 0x4698, 0xc4b0, 0x2cda, 0x011b, 0x0000, 0x1f88,
490*adcb0a62SAndroid Build Coastguard Worker 0x0004, 0x0006, 0x001c, 0x6261, 0x742e, 0x7478, 0x5455, 0x0009, 0x7c03, 0x3a09, 0x7c55, 0x3a09,
491*adcb0a62SAndroid Build Coastguard Worker 0x7555, 0x0b78, 0x0100, 0x8904, 0x0042, 0x0400, 0x1388, 0x0000, 0xc2ed, 0x0d31, 0x0000, 0x030c,
492*adcb0a62SAndroid Build Coastguard Worker 0x7fa0, 0x3b2e, 0x22ff, 0xa2aa, 0x841f, 0x45fc, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555,
493*adcb0a62SAndroid Build Coastguard Worker 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555,
494*adcb0a62SAndroid Build Coastguard Worker 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555,
495*adcb0a62SAndroid Build Coastguard Worker 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555,
496*adcb0a62SAndroid Build Coastguard Worker 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555,
497*adcb0a62SAndroid Build Coastguard Worker 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555,
498*adcb0a62SAndroid Build Coastguard Worker 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555,
499*adcb0a62SAndroid Build Coastguard Worker 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555,
500*adcb0a62SAndroid Build Coastguard Worker 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555,
501*adcb0a62SAndroid Build Coastguard Worker 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555,
502*adcb0a62SAndroid Build Coastguard Worker 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555,
503*adcb0a62SAndroid Build Coastguard Worker 0x5555, 0x5555, 0x5555, 0x5555, 0xdd55, 0x502c, 0x014b, 0x1e02, 0x1403, 0x0000, 0x0800, 0xd200,
504*adcb0a62SAndroid Build Coastguard Worker 0x9851, 0xb046, 0xdac4, 0x1b2c, 0x0001, 0x8800, 0x041f, 0x0600, 0x1800, 0x0000, 0x0000, 0x0100,
505*adcb0a62SAndroid Build Coastguard Worker 0x0000, 0xa000, 0x0081, 0x0000, 0x6100, 0x2e62, 0x7874, 0x5574, 0x0554, 0x0300, 0x097c, 0x553a,
506*adcb0a62SAndroid Build Coastguard Worker 0x7875, 0x000b, 0x0401, 0x4289, 0x0000, 0x8804, 0x0013, 0x5000, 0x054b, 0x0006, 0x0000, 0x0100,
507*adcb0a62SAndroid Build Coastguard Worker 0x0100, 0x4c00, 0x0000, 0x5b00, 0x0001, 0x0000, 0x0000};
508*adcb0a62SAndroid Build Coastguard Worker
509*adcb0a62SAndroid Build Coastguard Worker static const std::string kAbTxtName("ab.txt");
510*adcb0a62SAndroid Build Coastguard Worker static const size_t kAbUncompressedSize = 270216;
511*adcb0a62SAndroid Build Coastguard Worker
TEST(ziparchive,EmptyEntries)512*adcb0a62SAndroid Build Coastguard Worker TEST(ziparchive, EmptyEntries) {
513*adcb0a62SAndroid Build Coastguard Worker TemporaryFile tmp_file;
514*adcb0a62SAndroid Build Coastguard Worker ASSERT_NE(-1, tmp_file.fd);
515*adcb0a62SAndroid Build Coastguard Worker ASSERT_TRUE(android::base::WriteFully(tmp_file.fd, kEmptyEntriesZip, sizeof(kEmptyEntriesZip)));
516*adcb0a62SAndroid Build Coastguard Worker
517*adcb0a62SAndroid Build Coastguard Worker ZipArchiveHandle handle;
518*adcb0a62SAndroid Build Coastguard Worker ASSERT_EQ(0, OpenArchiveFd(tmp_file.fd, "EmptyEntriesTest", &handle, false));
519*adcb0a62SAndroid Build Coastguard Worker
520*adcb0a62SAndroid Build Coastguard Worker ZipEntry64 entry;
521*adcb0a62SAndroid Build Coastguard Worker ASSERT_EQ(0, FindEntry(handle, "empty.txt", &entry));
522*adcb0a62SAndroid Build Coastguard Worker ASSERT_EQ(0u, entry.uncompressed_length);
523*adcb0a62SAndroid Build Coastguard Worker // Extraction to a 1 byte buffer should succeed.
524*adcb0a62SAndroid Build Coastguard Worker uint8_t buffer[1];
525*adcb0a62SAndroid Build Coastguard Worker ASSERT_EQ(0, ExtractToMemory(handle, &entry, buffer, 1));
526*adcb0a62SAndroid Build Coastguard Worker // Extraction to an empty buffer should succeed.
527*adcb0a62SAndroid Build Coastguard Worker ASSERT_EQ(0, ExtractToMemory(handle, &entry, nullptr, 0));
528*adcb0a62SAndroid Build Coastguard Worker
529*adcb0a62SAndroid Build Coastguard Worker TemporaryFile tmp_output_file;
530*adcb0a62SAndroid Build Coastguard Worker ASSERT_NE(-1, tmp_output_file.fd);
531*adcb0a62SAndroid Build Coastguard Worker ASSERT_EQ(0, ExtractEntryToFile(handle, &entry, tmp_output_file.fd));
532*adcb0a62SAndroid Build Coastguard Worker
533*adcb0a62SAndroid Build Coastguard Worker struct stat stat_buf;
534*adcb0a62SAndroid Build Coastguard Worker ASSERT_EQ(0, fstat(tmp_output_file.fd, &stat_buf));
535*adcb0a62SAndroid Build Coastguard Worker ASSERT_EQ(0, stat_buf.st_size);
536*adcb0a62SAndroid Build Coastguard Worker }
537*adcb0a62SAndroid Build Coastguard Worker
TEST(ziparchive,EntryLargerThan32K)538*adcb0a62SAndroid Build Coastguard Worker TEST(ziparchive, EntryLargerThan32K) {
539*adcb0a62SAndroid Build Coastguard Worker TemporaryFile tmp_file;
540*adcb0a62SAndroid Build Coastguard Worker ASSERT_NE(-1, tmp_file.fd);
541*adcb0a62SAndroid Build Coastguard Worker ASSERT_TRUE(android::base::WriteFully(tmp_file.fd, reinterpret_cast<const uint8_t*>(kAbZip),
542*adcb0a62SAndroid Build Coastguard Worker sizeof(kAbZip) - 1));
543*adcb0a62SAndroid Build Coastguard Worker ZipArchiveHandle handle;
544*adcb0a62SAndroid Build Coastguard Worker ASSERT_EQ(0, OpenArchiveFd(tmp_file.fd, "EntryLargerThan32KTest", &handle, false));
545*adcb0a62SAndroid Build Coastguard Worker
546*adcb0a62SAndroid Build Coastguard Worker ZipEntry64 entry;
547*adcb0a62SAndroid Build Coastguard Worker ASSERT_EQ(0, FindEntry(handle, kAbTxtName, &entry));
548*adcb0a62SAndroid Build Coastguard Worker ASSERT_EQ(kAbUncompressedSize, entry.uncompressed_length);
549*adcb0a62SAndroid Build Coastguard Worker
550*adcb0a62SAndroid Build Coastguard Worker // Extract the entry to memory.
551*adcb0a62SAndroid Build Coastguard Worker std::vector<uint8_t> buffer(kAbUncompressedSize);
552*adcb0a62SAndroid Build Coastguard Worker ASSERT_EQ(0, ExtractToMemory(handle, &entry, &buffer[0], static_cast<uint32_t>(buffer.size())));
553*adcb0a62SAndroid Build Coastguard Worker
554*adcb0a62SAndroid Build Coastguard Worker // Extract the entry to a file.
555*adcb0a62SAndroid Build Coastguard Worker TemporaryFile tmp_output_file;
556*adcb0a62SAndroid Build Coastguard Worker ASSERT_NE(-1, tmp_output_file.fd);
557*adcb0a62SAndroid Build Coastguard Worker ASSERT_EQ(0, ExtractEntryToFile(handle, &entry, tmp_output_file.fd));
558*adcb0a62SAndroid Build Coastguard Worker
559*adcb0a62SAndroid Build Coastguard Worker // Make sure the extracted file size is as expected.
560*adcb0a62SAndroid Build Coastguard Worker struct stat stat_buf;
561*adcb0a62SAndroid Build Coastguard Worker ASSERT_EQ(0, fstat(tmp_output_file.fd, &stat_buf));
562*adcb0a62SAndroid Build Coastguard Worker ASSERT_EQ(kAbUncompressedSize, static_cast<size_t>(stat_buf.st_size));
563*adcb0a62SAndroid Build Coastguard Worker
564*adcb0a62SAndroid Build Coastguard Worker // Read the file back to a buffer and make sure the contents are
565*adcb0a62SAndroid Build Coastguard Worker // the same as the memory buffer we extracted directly to.
566*adcb0a62SAndroid Build Coastguard Worker std::vector<uint8_t> file_contents(kAbUncompressedSize);
567*adcb0a62SAndroid Build Coastguard Worker ASSERT_EQ(0, lseek(tmp_output_file.fd, 0, SEEK_SET));
568*adcb0a62SAndroid Build Coastguard Worker ASSERT_TRUE(android::base::ReadFully(tmp_output_file.fd, &file_contents[0], file_contents.size()));
569*adcb0a62SAndroid Build Coastguard Worker ASSERT_EQ(file_contents, buffer);
570*adcb0a62SAndroid Build Coastguard Worker
571*adcb0a62SAndroid Build Coastguard Worker for (int i = 0; i < 90072; ++i) {
572*adcb0a62SAndroid Build Coastguard Worker const uint8_t* line = &file_contents[0] + (3 * i);
573*adcb0a62SAndroid Build Coastguard Worker ASSERT_EQ('a', line[0]);
574*adcb0a62SAndroid Build Coastguard Worker ASSERT_EQ('b', line[1]);
575*adcb0a62SAndroid Build Coastguard Worker ASSERT_EQ('\n', line[2]);
576*adcb0a62SAndroid Build Coastguard Worker }
577*adcb0a62SAndroid Build Coastguard Worker }
578*adcb0a62SAndroid Build Coastguard Worker
TEST(ziparchive,TrailerAfterEOCD)579*adcb0a62SAndroid Build Coastguard Worker TEST(ziparchive, TrailerAfterEOCD) {
580*adcb0a62SAndroid Build Coastguard Worker TemporaryFile tmp_file;
581*adcb0a62SAndroid Build Coastguard Worker ASSERT_NE(-1, tmp_file.fd);
582*adcb0a62SAndroid Build Coastguard Worker
583*adcb0a62SAndroid Build Coastguard Worker // Create a file with 8 bytes of random garbage.
584*adcb0a62SAndroid Build Coastguard Worker static const uint8_t trailer[] = {'A', 'n', 'd', 'r', 'o', 'i', 'd', 'z'};
585*adcb0a62SAndroid Build Coastguard Worker ASSERT_TRUE(android::base::WriteFully(tmp_file.fd, kEmptyEntriesZip, sizeof(kEmptyEntriesZip)));
586*adcb0a62SAndroid Build Coastguard Worker ASSERT_TRUE(android::base::WriteFully(tmp_file.fd, trailer, sizeof(trailer)));
587*adcb0a62SAndroid Build Coastguard Worker
588*adcb0a62SAndroid Build Coastguard Worker ZipArchiveHandle handle;
589*adcb0a62SAndroid Build Coastguard Worker ASSERT_GT(0, OpenArchiveFd(tmp_file.fd, "EmptyEntriesTest", &handle, false));
590*adcb0a62SAndroid Build Coastguard Worker }
591*adcb0a62SAndroid Build Coastguard Worker
TEST(ziparchive,ExtractToFile)592*adcb0a62SAndroid Build Coastguard Worker TEST(ziparchive, ExtractToFile) {
593*adcb0a62SAndroid Build Coastguard Worker TemporaryFile tmp_file;
594*adcb0a62SAndroid Build Coastguard Worker ASSERT_NE(-1, tmp_file.fd);
595*adcb0a62SAndroid Build Coastguard Worker const uint8_t data[8] = {'1', '2', '3', '4', '5', '6', '7', '8'};
596*adcb0a62SAndroid Build Coastguard Worker const size_t data_size = sizeof(data);
597*adcb0a62SAndroid Build Coastguard Worker
598*adcb0a62SAndroid Build Coastguard Worker ASSERT_TRUE(android::base::WriteFully(tmp_file.fd, data, data_size));
599*adcb0a62SAndroid Build Coastguard Worker
600*adcb0a62SAndroid Build Coastguard Worker ZipArchiveHandle handle;
601*adcb0a62SAndroid Build Coastguard Worker ASSERT_EQ(0, OpenArchiveWrapper(kValidZip, &handle));
602*adcb0a62SAndroid Build Coastguard Worker
603*adcb0a62SAndroid Build Coastguard Worker ZipEntry64 entry;
604*adcb0a62SAndroid Build Coastguard Worker ASSERT_EQ(0, FindEntry(handle, "a.txt", &entry));
605*adcb0a62SAndroid Build Coastguard Worker ASSERT_EQ(0, ExtractEntryToFile(handle, &entry, tmp_file.fd));
606*adcb0a62SAndroid Build Coastguard Worker
607*adcb0a62SAndroid Build Coastguard Worker // Assert that the first 8 bytes of the file haven't been clobbered.
608*adcb0a62SAndroid Build Coastguard Worker uint8_t read_buffer[data_size];
609*adcb0a62SAndroid Build Coastguard Worker ASSERT_EQ(0, lseek(tmp_file.fd, 0, SEEK_SET));
610*adcb0a62SAndroid Build Coastguard Worker ASSERT_TRUE(android::base::ReadFully(tmp_file.fd, read_buffer, data_size));
611*adcb0a62SAndroid Build Coastguard Worker ASSERT_EQ(0, memcmp(read_buffer, data, data_size));
612*adcb0a62SAndroid Build Coastguard Worker
613*adcb0a62SAndroid Build Coastguard Worker // Assert that the remainder of the file contains the incompressed data.
614*adcb0a62SAndroid Build Coastguard Worker std::vector<uint8_t> uncompressed_data(static_cast<size_t>(entry.uncompressed_length));
615*adcb0a62SAndroid Build Coastguard Worker ASSERT_TRUE(android::base::ReadFully(tmp_file.fd, uncompressed_data.data(),
616*adcb0a62SAndroid Build Coastguard Worker static_cast<size_t>(entry.uncompressed_length)));
617*adcb0a62SAndroid Build Coastguard Worker ASSERT_EQ(0, memcmp(&uncompressed_data[0], kATxtContents.data(), kATxtContents.size()));
618*adcb0a62SAndroid Build Coastguard Worker
619*adcb0a62SAndroid Build Coastguard Worker // Assert that the total length of the file is sane
620*adcb0a62SAndroid Build Coastguard Worker ASSERT_EQ(static_cast<ssize_t>(data_size + kATxtContents.size()),
621*adcb0a62SAndroid Build Coastguard Worker lseek(tmp_file.fd, 0, SEEK_END));
622*adcb0a62SAndroid Build Coastguard Worker }
623*adcb0a62SAndroid Build Coastguard Worker
624*adcb0a62SAndroid Build Coastguard Worker #if !defined(_WIN32)
TEST(ziparchive,OpenFromMemory)625*adcb0a62SAndroid Build Coastguard Worker TEST(ziparchive, OpenFromMemory) {
626*adcb0a62SAndroid Build Coastguard Worker const std::string zip_path = test_data_dir + "/dummy-update.zip";
627*adcb0a62SAndroid Build Coastguard Worker android::base::unique_fd fd(open(zip_path.c_str(), O_RDONLY | O_BINARY));
628*adcb0a62SAndroid Build Coastguard Worker ASSERT_NE(-1, fd);
629*adcb0a62SAndroid Build Coastguard Worker struct stat sb;
630*adcb0a62SAndroid Build Coastguard Worker ASSERT_EQ(0, fstat(fd, &sb));
631*adcb0a62SAndroid Build Coastguard Worker
632*adcb0a62SAndroid Build Coastguard Worker // Memory map the file first and open the archive from the memory region.
633*adcb0a62SAndroid Build Coastguard Worker auto file_map{
634*adcb0a62SAndroid Build Coastguard Worker android::base::MappedFile::FromFd(fd, 0, static_cast<size_t>(sb.st_size), PROT_READ)};
635*adcb0a62SAndroid Build Coastguard Worker ZipArchiveHandle handle;
636*adcb0a62SAndroid Build Coastguard Worker ASSERT_EQ(0,
637*adcb0a62SAndroid Build Coastguard Worker OpenArchiveFromMemory(file_map->data(), file_map->size(), zip_path.c_str(), &handle));
638*adcb0a62SAndroid Build Coastguard Worker
639*adcb0a62SAndroid Build Coastguard Worker // Assert one entry can be found and extracted correctly.
640*adcb0a62SAndroid Build Coastguard Worker ZipEntry64 binary_entry;
641*adcb0a62SAndroid Build Coastguard Worker ASSERT_EQ(0, FindEntry(handle, "META-INF/com/google/android/update-binary", &binary_entry));
642*adcb0a62SAndroid Build Coastguard Worker TemporaryFile tmp_binary;
643*adcb0a62SAndroid Build Coastguard Worker ASSERT_NE(-1, tmp_binary.fd);
644*adcb0a62SAndroid Build Coastguard Worker ASSERT_EQ(0, ExtractEntryToFile(handle, &binary_entry, tmp_binary.fd));
645*adcb0a62SAndroid Build Coastguard Worker }
646*adcb0a62SAndroid Build Coastguard Worker #endif
647*adcb0a62SAndroid Build Coastguard Worker
ZipArchiveStreamTest(ZipArchiveHandle & handle,const std::string & entry_name,bool raw,bool verified,ZipEntry * entry,std::vector<uint8_t> * read_data)648*adcb0a62SAndroid Build Coastguard Worker static void ZipArchiveStreamTest(ZipArchiveHandle& handle, const std::string& entry_name, bool raw,
649*adcb0a62SAndroid Build Coastguard Worker bool verified, ZipEntry* entry, std::vector<uint8_t>* read_data) {
650*adcb0a62SAndroid Build Coastguard Worker ASSERT_EQ(0, FindEntry(handle, entry_name, entry));
651*adcb0a62SAndroid Build Coastguard Worker std::unique_ptr<ZipArchiveStreamEntry> stream;
652*adcb0a62SAndroid Build Coastguard Worker if (raw) {
653*adcb0a62SAndroid Build Coastguard Worker stream.reset(ZipArchiveStreamEntry::CreateRaw(handle, *entry));
654*adcb0a62SAndroid Build Coastguard Worker if (entry->method == kCompressStored) {
655*adcb0a62SAndroid Build Coastguard Worker read_data->resize(static_cast<size_t>(entry->uncompressed_length));
656*adcb0a62SAndroid Build Coastguard Worker } else {
657*adcb0a62SAndroid Build Coastguard Worker read_data->resize(static_cast<size_t>(entry->compressed_length));
658*adcb0a62SAndroid Build Coastguard Worker }
659*adcb0a62SAndroid Build Coastguard Worker } else {
660*adcb0a62SAndroid Build Coastguard Worker stream.reset(ZipArchiveStreamEntry::Create(handle, *entry));
661*adcb0a62SAndroid Build Coastguard Worker read_data->resize(static_cast<size_t>(entry->uncompressed_length));
662*adcb0a62SAndroid Build Coastguard Worker }
663*adcb0a62SAndroid Build Coastguard Worker uint8_t* read_data_ptr = read_data->data();
664*adcb0a62SAndroid Build Coastguard Worker ASSERT_TRUE(stream.get() != nullptr);
665*adcb0a62SAndroid Build Coastguard Worker const std::vector<uint8_t>* data;
666*adcb0a62SAndroid Build Coastguard Worker uint64_t total_size = 0;
667*adcb0a62SAndroid Build Coastguard Worker while ((data = stream->Read()) != nullptr) {
668*adcb0a62SAndroid Build Coastguard Worker total_size += data->size();
669*adcb0a62SAndroid Build Coastguard Worker memcpy(read_data_ptr, data->data(), data->size());
670*adcb0a62SAndroid Build Coastguard Worker read_data_ptr += data->size();
671*adcb0a62SAndroid Build Coastguard Worker }
672*adcb0a62SAndroid Build Coastguard Worker ASSERT_EQ(verified, stream->Verify());
673*adcb0a62SAndroid Build Coastguard Worker ASSERT_EQ(total_size, read_data->size());
674*adcb0a62SAndroid Build Coastguard Worker }
675*adcb0a62SAndroid Build Coastguard Worker
ZipArchiveStreamTestUsingContents(const std::string & zip_file,const std::string & entry_name,const std::vector<uint8_t> & contents,bool raw)676*adcb0a62SAndroid Build Coastguard Worker static void ZipArchiveStreamTestUsingContents(const std::string& zip_file,
677*adcb0a62SAndroid Build Coastguard Worker const std::string& entry_name,
678*adcb0a62SAndroid Build Coastguard Worker const std::vector<uint8_t>& contents, bool raw) {
679*adcb0a62SAndroid Build Coastguard Worker ZipArchiveHandle handle;
680*adcb0a62SAndroid Build Coastguard Worker ASSERT_EQ(0, OpenArchiveWrapper(zip_file, &handle));
681*adcb0a62SAndroid Build Coastguard Worker
682*adcb0a62SAndroid Build Coastguard Worker ZipEntry entry;
683*adcb0a62SAndroid Build Coastguard Worker std::vector<uint8_t> read_data;
684*adcb0a62SAndroid Build Coastguard Worker ZipArchiveStreamTest(handle, entry_name, raw, true, &entry, &read_data);
685*adcb0a62SAndroid Build Coastguard Worker
686*adcb0a62SAndroid Build Coastguard Worker ASSERT_EQ(contents.size(), read_data.size());
687*adcb0a62SAndroid Build Coastguard Worker ASSERT_TRUE(memcmp(read_data.data(), contents.data(), read_data.size()) == 0);
688*adcb0a62SAndroid Build Coastguard Worker
689*adcb0a62SAndroid Build Coastguard Worker CloseArchive(handle);
690*adcb0a62SAndroid Build Coastguard Worker }
691*adcb0a62SAndroid Build Coastguard Worker
ZipArchiveStreamTestUsingMemory(const std::string & zip_file,const std::string & entry_name)692*adcb0a62SAndroid Build Coastguard Worker static void ZipArchiveStreamTestUsingMemory(const std::string& zip_file,
693*adcb0a62SAndroid Build Coastguard Worker const std::string& entry_name) {
694*adcb0a62SAndroid Build Coastguard Worker ZipArchiveHandle handle;
695*adcb0a62SAndroid Build Coastguard Worker ASSERT_EQ(0, OpenArchiveWrapper(zip_file, &handle));
696*adcb0a62SAndroid Build Coastguard Worker
697*adcb0a62SAndroid Build Coastguard Worker ZipEntry entry;
698*adcb0a62SAndroid Build Coastguard Worker std::vector<uint8_t> read_data;
699*adcb0a62SAndroid Build Coastguard Worker ZipArchiveStreamTest(handle, entry_name, false, true, &entry, &read_data);
700*adcb0a62SAndroid Build Coastguard Worker
701*adcb0a62SAndroid Build Coastguard Worker std::vector<uint8_t> cmp_data(static_cast<size_t>(entry.uncompressed_length));
702*adcb0a62SAndroid Build Coastguard Worker ASSERT_EQ(entry.uncompressed_length, read_data.size());
703*adcb0a62SAndroid Build Coastguard Worker ASSERT_EQ(
704*adcb0a62SAndroid Build Coastguard Worker 0, ExtractToMemory(handle, &entry, cmp_data.data(), static_cast<uint32_t>(cmp_data.size())));
705*adcb0a62SAndroid Build Coastguard Worker ASSERT_TRUE(memcmp(read_data.data(), cmp_data.data(), read_data.size()) == 0);
706*adcb0a62SAndroid Build Coastguard Worker
707*adcb0a62SAndroid Build Coastguard Worker CloseArchive(handle);
708*adcb0a62SAndroid Build Coastguard Worker }
709*adcb0a62SAndroid Build Coastguard Worker
TEST(ziparchive,StreamCompressed)710*adcb0a62SAndroid Build Coastguard Worker TEST(ziparchive, StreamCompressed) {
711*adcb0a62SAndroid Build Coastguard Worker ZipArchiveStreamTestUsingContents(kValidZip, "a.txt", kATxtContents, false);
712*adcb0a62SAndroid Build Coastguard Worker }
713*adcb0a62SAndroid Build Coastguard Worker
TEST(ziparchive,StreamUncompressed)714*adcb0a62SAndroid Build Coastguard Worker TEST(ziparchive, StreamUncompressed) {
715*adcb0a62SAndroid Build Coastguard Worker ZipArchiveStreamTestUsingContents(kValidZip, "b.txt", kBTxtContents, false);
716*adcb0a62SAndroid Build Coastguard Worker }
717*adcb0a62SAndroid Build Coastguard Worker
TEST(ziparchive,StreamRawCompressed)718*adcb0a62SAndroid Build Coastguard Worker TEST(ziparchive, StreamRawCompressed) {
719*adcb0a62SAndroid Build Coastguard Worker ZipArchiveStreamTestUsingContents(kValidZip, "a.txt", kATxtContentsCompressed, true);
720*adcb0a62SAndroid Build Coastguard Worker }
721*adcb0a62SAndroid Build Coastguard Worker
TEST(ziparchive,StreamRawUncompressed)722*adcb0a62SAndroid Build Coastguard Worker TEST(ziparchive, StreamRawUncompressed) {
723*adcb0a62SAndroid Build Coastguard Worker ZipArchiveStreamTestUsingContents(kValidZip, "b.txt", kBTxtContents, true);
724*adcb0a62SAndroid Build Coastguard Worker }
725*adcb0a62SAndroid Build Coastguard Worker
TEST(ziparchive,StreamLargeCompressed)726*adcb0a62SAndroid Build Coastguard Worker TEST(ziparchive, StreamLargeCompressed) {
727*adcb0a62SAndroid Build Coastguard Worker ZipArchiveStreamTestUsingMemory(kLargeZip, "compress.txt");
728*adcb0a62SAndroid Build Coastguard Worker }
729*adcb0a62SAndroid Build Coastguard Worker
TEST(ziparchive,StreamLargeUncompressed)730*adcb0a62SAndroid Build Coastguard Worker TEST(ziparchive, StreamLargeUncompressed) {
731*adcb0a62SAndroid Build Coastguard Worker ZipArchiveStreamTestUsingMemory(kLargeZip, "uncompress.txt");
732*adcb0a62SAndroid Build Coastguard Worker }
733*adcb0a62SAndroid Build Coastguard Worker
TEST(ziparchive,StreamCompressedBadCrc)734*adcb0a62SAndroid Build Coastguard Worker TEST(ziparchive, StreamCompressedBadCrc) {
735*adcb0a62SAndroid Build Coastguard Worker ZipArchiveHandle handle;
736*adcb0a62SAndroid Build Coastguard Worker ASSERT_EQ(0, OpenArchiveWrapper(kBadCrcZip, &handle));
737*adcb0a62SAndroid Build Coastguard Worker
738*adcb0a62SAndroid Build Coastguard Worker ZipEntry entry;
739*adcb0a62SAndroid Build Coastguard Worker std::vector<uint8_t> read_data;
740*adcb0a62SAndroid Build Coastguard Worker ZipArchiveStreamTest(handle, "a.txt", false, false, &entry, &read_data);
741*adcb0a62SAndroid Build Coastguard Worker
742*adcb0a62SAndroid Build Coastguard Worker CloseArchive(handle);
743*adcb0a62SAndroid Build Coastguard Worker }
744*adcb0a62SAndroid Build Coastguard Worker
TEST(ziparchive,StreamUncompressedBadCrc)745*adcb0a62SAndroid Build Coastguard Worker TEST(ziparchive, StreamUncompressedBadCrc) {
746*adcb0a62SAndroid Build Coastguard Worker ZipArchiveHandle handle;
747*adcb0a62SAndroid Build Coastguard Worker ASSERT_EQ(0, OpenArchiveWrapper(kBadCrcZip, &handle));
748*adcb0a62SAndroid Build Coastguard Worker
749*adcb0a62SAndroid Build Coastguard Worker ZipEntry entry;
750*adcb0a62SAndroid Build Coastguard Worker std::vector<uint8_t> read_data;
751*adcb0a62SAndroid Build Coastguard Worker ZipArchiveStreamTest(handle, "b.txt", false, false, &entry, &read_data);
752*adcb0a62SAndroid Build Coastguard Worker
753*adcb0a62SAndroid Build Coastguard Worker CloseArchive(handle);
754*adcb0a62SAndroid Build Coastguard Worker }
755*adcb0a62SAndroid Build Coastguard Worker
756*adcb0a62SAndroid Build Coastguard Worker // Generated using the following Java program:
757*adcb0a62SAndroid Build Coastguard Worker // public static void main(String[] foo) throws Exception {
758*adcb0a62SAndroid Build Coastguard Worker // FileOutputStream fos = new
759*adcb0a62SAndroid Build Coastguard Worker // FileOutputStream("/tmp/data_descriptor.zip");
760*adcb0a62SAndroid Build Coastguard Worker // ZipOutputStream zos = new ZipOutputStream(fos);
761*adcb0a62SAndroid Build Coastguard Worker // ZipEntry64 ze = new ZipEntry64("name");
762*adcb0a62SAndroid Build Coastguard Worker // ze.setMethod(ZipEntry64.DEFLATED);
763*adcb0a62SAndroid Build Coastguard Worker // zos.putNextEntry(ze);
764*adcb0a62SAndroid Build Coastguard Worker // zos.write("abdcdefghijk".getBytes());
765*adcb0a62SAndroid Build Coastguard Worker // zos.closeEntry();
766*adcb0a62SAndroid Build Coastguard Worker // zos.close();
767*adcb0a62SAndroid Build Coastguard Worker // }
768*adcb0a62SAndroid Build Coastguard Worker //
769*adcb0a62SAndroid Build Coastguard Worker // cat /tmp/data_descriptor.zip | xxd -i
770*adcb0a62SAndroid Build Coastguard Worker //
771*adcb0a62SAndroid Build Coastguard Worker static const std::vector<uint8_t> kDataDescriptorZipFile{
772*adcb0a62SAndroid Build Coastguard Worker 0x50, 0x4b, 0x03, 0x04, 0x14, 0x00, 0x08, 0x08, 0x08, 0x00, 0x30, 0x59, 0xce, 0x4a, 0x00, 0x00,
773*adcb0a62SAndroid Build Coastguard Worker 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x6e, 0x61,
774*adcb0a62SAndroid Build Coastguard Worker 0x6d, 0x65, 0x4b, 0x4c, 0x4a, 0x49, 0x4e, 0x49, 0x4d, 0x4b, 0xcf, 0xc8, 0xcc, 0xca, 0x06, 0x00,
775*adcb0a62SAndroid Build Coastguard Worker //[sig---------------], [crc32---------------], [csize---------------], [size----------------]
776*adcb0a62SAndroid Build Coastguard Worker 0x50, 0x4b, 0x07, 0x08, 0x3d, 0x4e, 0x0e, 0xf9, 0x0e, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
777*adcb0a62SAndroid Build Coastguard Worker 0x50, 0x4b, 0x01, 0x02, 0x14, 0x00, 0x14, 0x00, 0x08, 0x08, 0x08, 0x00, 0x30, 0x59, 0xce, 0x4a,
778*adcb0a62SAndroid Build Coastguard Worker 0x3d, 0x4e, 0x0e, 0xf9, 0x0e, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
779*adcb0a62SAndroid Build Coastguard Worker 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6e, 0x61,
780*adcb0a62SAndroid Build Coastguard Worker 0x6d, 0x65, 0x50, 0x4b, 0x05, 0x06, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x32, 0x00,
781*adcb0a62SAndroid Build Coastguard Worker 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00};
782*adcb0a62SAndroid Build Coastguard Worker
783*adcb0a62SAndroid Build Coastguard Worker // The offsets of the data descriptor in this file, so we can mess with
784*adcb0a62SAndroid Build Coastguard Worker // them later in the test.
785*adcb0a62SAndroid Build Coastguard Worker static constexpr uint32_t kDataDescriptorOffset = 48;
786*adcb0a62SAndroid Build Coastguard Worker static constexpr uint32_t kCSizeOffset = kDataDescriptorOffset + 8;
787*adcb0a62SAndroid Build Coastguard Worker static constexpr uint32_t kSizeOffset = kCSizeOffset + 4;
788*adcb0a62SAndroid Build Coastguard Worker
ExtractEntryToMemory(const std::vector<uint8_t> & zip_data,std::vector<uint8_t> * entry_out,int32_t * error_code_out)789*adcb0a62SAndroid Build Coastguard Worker static void ExtractEntryToMemory(const std::vector<uint8_t>& zip_data,
790*adcb0a62SAndroid Build Coastguard Worker std::vector<uint8_t>* entry_out, int32_t* error_code_out) {
791*adcb0a62SAndroid Build Coastguard Worker TemporaryFile tmp_file;
792*adcb0a62SAndroid Build Coastguard Worker ASSERT_NE(-1, tmp_file.fd);
793*adcb0a62SAndroid Build Coastguard Worker ASSERT_TRUE(android::base::WriteFully(tmp_file.fd, &zip_data[0], zip_data.size()));
794*adcb0a62SAndroid Build Coastguard Worker ZipArchiveHandle handle;
795*adcb0a62SAndroid Build Coastguard Worker ASSERT_EQ(0, OpenArchiveFd(tmp_file.fd, "ExtractEntryToMemory", &handle, false));
796*adcb0a62SAndroid Build Coastguard Worker
797*adcb0a62SAndroid Build Coastguard Worker // This function expects a variant of kDataDescriptorZipFile, for look for
798*adcb0a62SAndroid Build Coastguard Worker // an entry whose name is "name" and whose size is 12 (contents =
799*adcb0a62SAndroid Build Coastguard Worker // "abdcdefghijk").
800*adcb0a62SAndroid Build Coastguard Worker ZipEntry64 entry;
801*adcb0a62SAndroid Build Coastguard Worker ASSERT_EQ(0, FindEntry(handle, "name", &entry));
802*adcb0a62SAndroid Build Coastguard Worker ASSERT_EQ(12u, entry.uncompressed_length);
803*adcb0a62SAndroid Build Coastguard Worker
804*adcb0a62SAndroid Build Coastguard Worker entry_out->resize(12);
805*adcb0a62SAndroid Build Coastguard Worker (*error_code_out) = ExtractToMemory(handle, &entry, &((*entry_out)[0]), 12);
806*adcb0a62SAndroid Build Coastguard Worker
807*adcb0a62SAndroid Build Coastguard Worker CloseArchive(handle);
808*adcb0a62SAndroid Build Coastguard Worker }
809*adcb0a62SAndroid Build Coastguard Worker
TEST(ziparchive,ValidDataDescriptors)810*adcb0a62SAndroid Build Coastguard Worker TEST(ziparchive, ValidDataDescriptors) {
811*adcb0a62SAndroid Build Coastguard Worker std::vector<uint8_t> entry;
812*adcb0a62SAndroid Build Coastguard Worker int32_t error_code = 0;
813*adcb0a62SAndroid Build Coastguard Worker ExtractEntryToMemory(kDataDescriptorZipFile, &entry, &error_code);
814*adcb0a62SAndroid Build Coastguard Worker
815*adcb0a62SAndroid Build Coastguard Worker ASSERT_EQ(0, error_code);
816*adcb0a62SAndroid Build Coastguard Worker ASSERT_EQ(12u, entry.size());
817*adcb0a62SAndroid Build Coastguard Worker ASSERT_EQ('a', entry[0]);
818*adcb0a62SAndroid Build Coastguard Worker ASSERT_EQ('k', entry[11]);
819*adcb0a62SAndroid Build Coastguard Worker }
820*adcb0a62SAndroid Build Coastguard Worker
TEST(ziparchive,InvalidDataDescriptors_csize)821*adcb0a62SAndroid Build Coastguard Worker TEST(ziparchive, InvalidDataDescriptors_csize) {
822*adcb0a62SAndroid Build Coastguard Worker std::vector<uint8_t> invalid_csize = kDataDescriptorZipFile;
823*adcb0a62SAndroid Build Coastguard Worker invalid_csize[kCSizeOffset] = 0xfe;
824*adcb0a62SAndroid Build Coastguard Worker
825*adcb0a62SAndroid Build Coastguard Worker std::vector<uint8_t> entry;
826*adcb0a62SAndroid Build Coastguard Worker int32_t error_code = 0;
827*adcb0a62SAndroid Build Coastguard Worker ExtractEntryToMemory(invalid_csize, &entry, &error_code);
828*adcb0a62SAndroid Build Coastguard Worker
829*adcb0a62SAndroid Build Coastguard Worker ASSERT_EQ(kInconsistentInformation, error_code);
830*adcb0a62SAndroid Build Coastguard Worker }
831*adcb0a62SAndroid Build Coastguard Worker
TEST(ziparchive,InvalidDataDescriptors_size)832*adcb0a62SAndroid Build Coastguard Worker TEST(ziparchive, InvalidDataDescriptors_size) {
833*adcb0a62SAndroid Build Coastguard Worker std::vector<uint8_t> invalid_size = kDataDescriptorZipFile;
834*adcb0a62SAndroid Build Coastguard Worker invalid_size[kSizeOffset] = 0xfe;
835*adcb0a62SAndroid Build Coastguard Worker
836*adcb0a62SAndroid Build Coastguard Worker std::vector<uint8_t> entry;
837*adcb0a62SAndroid Build Coastguard Worker int32_t error_code = 0;
838*adcb0a62SAndroid Build Coastguard Worker ExtractEntryToMemory(invalid_size, &entry, &error_code);
839*adcb0a62SAndroid Build Coastguard Worker
840*adcb0a62SAndroid Build Coastguard Worker ASSERT_EQ(kInconsistentInformation, error_code);
841*adcb0a62SAndroid Build Coastguard Worker }
842*adcb0a62SAndroid Build Coastguard Worker
TEST(ziparchive,ErrorCodeString)843*adcb0a62SAndroid Build Coastguard Worker TEST(ziparchive, ErrorCodeString) {
844*adcb0a62SAndroid Build Coastguard Worker ASSERT_STREQ("Success", ErrorCodeString(0));
845*adcb0a62SAndroid Build Coastguard Worker
846*adcb0a62SAndroid Build Coastguard Worker // Out of bounds.
847*adcb0a62SAndroid Build Coastguard Worker ASSERT_STREQ("Unknown return code", ErrorCodeString(1));
848*adcb0a62SAndroid Build Coastguard Worker ASSERT_STRNE("Unknown return code", ErrorCodeString(kLastErrorCode));
849*adcb0a62SAndroid Build Coastguard Worker ASSERT_STREQ("Unknown return code", ErrorCodeString(kLastErrorCode - 1));
850*adcb0a62SAndroid Build Coastguard Worker
851*adcb0a62SAndroid Build Coastguard Worker ASSERT_STREQ("I/O error", ErrorCodeString(kIoError));
852*adcb0a62SAndroid Build Coastguard Worker }
853*adcb0a62SAndroid Build Coastguard Worker
854*adcb0a62SAndroid Build Coastguard Worker // A zip file whose local file header at offset zero is corrupted.
855*adcb0a62SAndroid Build Coastguard Worker //
856*adcb0a62SAndroid Build Coastguard Worker // ---------------
857*adcb0a62SAndroid Build Coastguard Worker // cat foo > a.txt
858*adcb0a62SAndroid Build Coastguard Worker // zip a.zip a.txt
859*adcb0a62SAndroid Build Coastguard Worker // cat a.zip | xxd -i
860*adcb0a62SAndroid Build Coastguard Worker //
861*adcb0a62SAndroid Build Coastguard Worker // Manual changes :
862*adcb0a62SAndroid Build Coastguard Worker // [2] = 0xff // Corrupt the LFH signature of entry 0.
863*adcb0a62SAndroid Build Coastguard Worker // [3] = 0xff // Corrupt the LFH signature of entry 0.
864*adcb0a62SAndroid Build Coastguard Worker static const std::vector<uint8_t> kZipFileWithBrokenLfhSignature{
865*adcb0a62SAndroid Build Coastguard Worker //[lfh-sig-----------], [lfh contents---------------------------------
866*adcb0a62SAndroid Build Coastguard Worker 0x50, 0x4b, 0xff, 0xff, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x80,
867*adcb0a62SAndroid Build Coastguard Worker //--------------------------------------------------------------------
868*adcb0a62SAndroid Build Coastguard Worker 0x09, 0x4b, 0xa8, 0x65, 0x32, 0x7e, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00,
869*adcb0a62SAndroid Build Coastguard Worker //-------------------------------] [file-name-----------------], [---
870*adcb0a62SAndroid Build Coastguard Worker 0x00, 0x00, 0x05, 0x00, 0x1c, 0x00, 0x61, 0x2e, 0x74, 0x78, 0x74, 0x55,
871*adcb0a62SAndroid Build Coastguard Worker // entry-contents------------------------------------------------------
872*adcb0a62SAndroid Build Coastguard Worker 0x54, 0x09, 0x00, 0x03, 0x51, 0x24, 0x8b, 0x59, 0x51, 0x24, 0x8b, 0x59,
873*adcb0a62SAndroid Build Coastguard Worker //--------------------------------------------------------------------
874*adcb0a62SAndroid Build Coastguard Worker 0x75, 0x78, 0x0b, 0x00, 0x01, 0x04, 0x89, 0x42, 0x00, 0x00, 0x04, 0x88,
875*adcb0a62SAndroid Build Coastguard Worker //-------------------------------------], [cd-record-sig-------], [---
876*adcb0a62SAndroid Build Coastguard Worker 0x13, 0x00, 0x00, 0x66, 0x6f, 0x6f, 0x0a, 0x50, 0x4b, 0x01, 0x02, 0x1e,
877*adcb0a62SAndroid Build Coastguard Worker // cd-record-----------------------------------------------------------
878*adcb0a62SAndroid Build Coastguard Worker 0x03, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x80, 0x09, 0x4b, 0xa8,
879*adcb0a62SAndroid Build Coastguard Worker //--------------------------------------------------------------------
880*adcb0a62SAndroid Build Coastguard Worker 0x65, 0x32, 0x7e, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x05,
881*adcb0a62SAndroid Build Coastguard Worker //--------------------------------------------------------------------
882*adcb0a62SAndroid Build Coastguard Worker 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xa0,
883*adcb0a62SAndroid Build Coastguard Worker //-] [lfh-file-header-off-], [file-name-----------------], [extra----
884*adcb0a62SAndroid Build Coastguard Worker 0x81, 0x00, 0x00, 0x00, 0x00, 0x61, 0x2e, 0x74, 0x78, 0x74, 0x55, 0x54,
885*adcb0a62SAndroid Build Coastguard Worker //--------------------------------------------------------------------
886*adcb0a62SAndroid Build Coastguard Worker 0x05, 0x00, 0x03, 0x51, 0x24, 0x8b, 0x59, 0x75, 0x78, 0x0b, 0x00, 0x01,
887*adcb0a62SAndroid Build Coastguard Worker //-------------------------------------------------------], [eocd-sig-
888*adcb0a62SAndroid Build Coastguard Worker 0x04, 0x89, 0x42, 0x00, 0x00, 0x04, 0x88, 0x13, 0x00, 0x00, 0x50, 0x4b,
889*adcb0a62SAndroid Build Coastguard Worker //-------], [---------------------------------------------------------
890*adcb0a62SAndroid Build Coastguard Worker 0x05, 0x06, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x4b, 0x00,
891*adcb0a62SAndroid Build Coastguard Worker //-------------------------------------------]
892*adcb0a62SAndroid Build Coastguard Worker 0x00, 0x00, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00};
893*adcb0a62SAndroid Build Coastguard Worker
TEST(ziparchive,BrokenLfhSignature)894*adcb0a62SAndroid Build Coastguard Worker TEST(ziparchive, BrokenLfhSignature) {
895*adcb0a62SAndroid Build Coastguard Worker TemporaryFile tmp_file;
896*adcb0a62SAndroid Build Coastguard Worker ASSERT_NE(-1, tmp_file.fd);
897*adcb0a62SAndroid Build Coastguard Worker ASSERT_TRUE(android::base::WriteFully(tmp_file.fd, &kZipFileWithBrokenLfhSignature[0],
898*adcb0a62SAndroid Build Coastguard Worker kZipFileWithBrokenLfhSignature.size()));
899*adcb0a62SAndroid Build Coastguard Worker ZipArchiveHandle handle;
900*adcb0a62SAndroid Build Coastguard Worker ASSERT_EQ(kInvalidFile, OpenArchiveFd(tmp_file.fd, "LeadingNonZipBytes", &handle, false));
901*adcb0a62SAndroid Build Coastguard Worker }
902*adcb0a62SAndroid Build Coastguard Worker
903*adcb0a62SAndroid Build Coastguard Worker class VectorReader final : public zip_archive::Reader {
904*adcb0a62SAndroid Build Coastguard Worker public:
VectorReader(const std::vector<uint8_t> & input)905*adcb0a62SAndroid Build Coastguard Worker VectorReader(const std::vector<uint8_t>& input) : Reader(), input_(input) {}
906*adcb0a62SAndroid Build Coastguard Worker
ReadAtOffset(uint8_t * buf,size_t len,off64_t offset) const907*adcb0a62SAndroid Build Coastguard Worker bool ReadAtOffset(uint8_t* buf, size_t len, off64_t offset) const {
908*adcb0a62SAndroid Build Coastguard Worker if ((offset + len) < input_.size()) {
909*adcb0a62SAndroid Build Coastguard Worker return false;
910*adcb0a62SAndroid Build Coastguard Worker }
911*adcb0a62SAndroid Build Coastguard Worker
912*adcb0a62SAndroid Build Coastguard Worker memcpy(buf, &input_[static_cast<size_t>(offset)], len);
913*adcb0a62SAndroid Build Coastguard Worker return true;
914*adcb0a62SAndroid Build Coastguard Worker }
915*adcb0a62SAndroid Build Coastguard Worker
916*adcb0a62SAndroid Build Coastguard Worker private:
917*adcb0a62SAndroid Build Coastguard Worker const std::vector<uint8_t>& input_;
918*adcb0a62SAndroid Build Coastguard Worker };
919*adcb0a62SAndroid Build Coastguard Worker
920*adcb0a62SAndroid Build Coastguard Worker class VectorWriter final : public zip_archive::Writer {
921*adcb0a62SAndroid Build Coastguard Worker public:
VectorWriter()922*adcb0a62SAndroid Build Coastguard Worker VectorWriter() : Writer() {}
923*adcb0a62SAndroid Build Coastguard Worker
Append(uint8_t * buf,size_t size)924*adcb0a62SAndroid Build Coastguard Worker bool Append(uint8_t* buf, size_t size) {
925*adcb0a62SAndroid Build Coastguard Worker output_.insert(output_.end(), buf, buf + size);
926*adcb0a62SAndroid Build Coastguard Worker return true;
927*adcb0a62SAndroid Build Coastguard Worker }
928*adcb0a62SAndroid Build Coastguard Worker
GetOutput()929*adcb0a62SAndroid Build Coastguard Worker std::vector<uint8_t>& GetOutput() { return output_; }
930*adcb0a62SAndroid Build Coastguard Worker
931*adcb0a62SAndroid Build Coastguard Worker private:
932*adcb0a62SAndroid Build Coastguard Worker std::vector<uint8_t> output_;
933*adcb0a62SAndroid Build Coastguard Worker };
934*adcb0a62SAndroid Build Coastguard Worker
935*adcb0a62SAndroid Build Coastguard Worker class BadReader final : public zip_archive::Reader {
936*adcb0a62SAndroid Build Coastguard Worker public:
BadReader()937*adcb0a62SAndroid Build Coastguard Worker BadReader() : Reader() {}
938*adcb0a62SAndroid Build Coastguard Worker
ReadAtOffset(uint8_t *,size_t,off64_t) const939*adcb0a62SAndroid Build Coastguard Worker bool ReadAtOffset(uint8_t*, size_t, off64_t) const { return false; }
940*adcb0a62SAndroid Build Coastguard Worker };
941*adcb0a62SAndroid Build Coastguard Worker
942*adcb0a62SAndroid Build Coastguard Worker class BadWriter final : public zip_archive::Writer {
943*adcb0a62SAndroid Build Coastguard Worker public:
BadWriter()944*adcb0a62SAndroid Build Coastguard Worker BadWriter() : Writer() {}
945*adcb0a62SAndroid Build Coastguard Worker
Append(uint8_t *,size_t)946*adcb0a62SAndroid Build Coastguard Worker bool Append(uint8_t*, size_t) { return false; }
947*adcb0a62SAndroid Build Coastguard Worker };
948*adcb0a62SAndroid Build Coastguard Worker
TEST(ziparchive,Inflate)949*adcb0a62SAndroid Build Coastguard Worker TEST(ziparchive, Inflate) {
950*adcb0a62SAndroid Build Coastguard Worker const uint32_t compressed_length = static_cast<uint32_t>(kATxtContentsCompressed.size());
951*adcb0a62SAndroid Build Coastguard Worker const uint32_t uncompressed_length = static_cast<uint32_t>(kATxtContents.size());
952*adcb0a62SAndroid Build Coastguard Worker
953*adcb0a62SAndroid Build Coastguard Worker const VectorReader reader(kATxtContentsCompressed);
954*adcb0a62SAndroid Build Coastguard Worker {
955*adcb0a62SAndroid Build Coastguard Worker VectorWriter writer;
956*adcb0a62SAndroid Build Coastguard Worker uint64_t crc_out = 0;
957*adcb0a62SAndroid Build Coastguard Worker
958*adcb0a62SAndroid Build Coastguard Worker int32_t ret =
959*adcb0a62SAndroid Build Coastguard Worker zip_archive::Inflate(reader, compressed_length, uncompressed_length, &writer, &crc_out);
960*adcb0a62SAndroid Build Coastguard Worker ASSERT_EQ(0, ret);
961*adcb0a62SAndroid Build Coastguard Worker ASSERT_EQ(kATxtContents, writer.GetOutput());
962*adcb0a62SAndroid Build Coastguard Worker ASSERT_EQ(0x950821C5u, crc_out);
963*adcb0a62SAndroid Build Coastguard Worker }
964*adcb0a62SAndroid Build Coastguard Worker
965*adcb0a62SAndroid Build Coastguard Worker {
966*adcb0a62SAndroid Build Coastguard Worker VectorWriter writer;
967*adcb0a62SAndroid Build Coastguard Worker int32_t ret =
968*adcb0a62SAndroid Build Coastguard Worker zip_archive::Inflate(reader, compressed_length, uncompressed_length, &writer, nullptr);
969*adcb0a62SAndroid Build Coastguard Worker ASSERT_EQ(0, ret);
970*adcb0a62SAndroid Build Coastguard Worker ASSERT_EQ(kATxtContents, writer.GetOutput());
971*adcb0a62SAndroid Build Coastguard Worker }
972*adcb0a62SAndroid Build Coastguard Worker
973*adcb0a62SAndroid Build Coastguard Worker {
974*adcb0a62SAndroid Build Coastguard Worker BadWriter writer;
975*adcb0a62SAndroid Build Coastguard Worker int32_t ret =
976*adcb0a62SAndroid Build Coastguard Worker zip_archive::Inflate(reader, compressed_length, uncompressed_length, &writer, nullptr);
977*adcb0a62SAndroid Build Coastguard Worker ASSERT_EQ(kIoError, ret);
978*adcb0a62SAndroid Build Coastguard Worker }
979*adcb0a62SAndroid Build Coastguard Worker
980*adcb0a62SAndroid Build Coastguard Worker {
981*adcb0a62SAndroid Build Coastguard Worker BadReader reader;
982*adcb0a62SAndroid Build Coastguard Worker VectorWriter writer;
983*adcb0a62SAndroid Build Coastguard Worker int32_t ret =
984*adcb0a62SAndroid Build Coastguard Worker zip_archive::Inflate(reader, compressed_length, uncompressed_length, &writer, nullptr);
985*adcb0a62SAndroid Build Coastguard Worker ASSERT_EQ(kIoError, ret);
986*adcb0a62SAndroid Build Coastguard Worker ASSERT_EQ(0u, writer.GetOutput().size());
987*adcb0a62SAndroid Build Coastguard Worker }
988*adcb0a62SAndroid Build Coastguard Worker }
989*adcb0a62SAndroid Build Coastguard Worker
990*adcb0a62SAndroid Build Coastguard Worker // The class constructs a zipfile with zip64 format, and test the parsing logic.
991*adcb0a62SAndroid Build Coastguard Worker class Zip64ParseTest : public ::testing::Test {
992*adcb0a62SAndroid Build Coastguard Worker protected:
993*adcb0a62SAndroid Build Coastguard Worker struct LocalFileEntry {
994*adcb0a62SAndroid Build Coastguard Worker std::vector<uint8_t> local_file_header;
995*adcb0a62SAndroid Build Coastguard Worker std::string file_name;
996*adcb0a62SAndroid Build Coastguard Worker std::vector<uint8_t> extended_field;
997*adcb0a62SAndroid Build Coastguard Worker // Fake data to mimic the compressed bytes in the zipfile.
998*adcb0a62SAndroid Build Coastguard Worker std::vector<uint8_t> compressed_bytes;
999*adcb0a62SAndroid Build Coastguard Worker std::vector<uint8_t> data_descriptor;
1000*adcb0a62SAndroid Build Coastguard Worker
GetSizeZip64ParseTest::LocalFileEntry1001*adcb0a62SAndroid Build Coastguard Worker size_t GetSize() const {
1002*adcb0a62SAndroid Build Coastguard Worker return local_file_header.size() + file_name.size() + extended_field.size() +
1003*adcb0a62SAndroid Build Coastguard Worker compressed_bytes.size() + data_descriptor.size();
1004*adcb0a62SAndroid Build Coastguard Worker }
1005*adcb0a62SAndroid Build Coastguard Worker
CopyToOutputZip64ParseTest::LocalFileEntry1006*adcb0a62SAndroid Build Coastguard Worker void CopyToOutput(std::vector<uint8_t>* output) const {
1007*adcb0a62SAndroid Build Coastguard Worker std::copy(local_file_header.begin(), local_file_header.end(), std::back_inserter(*output));
1008*adcb0a62SAndroid Build Coastguard Worker std::copy(file_name.begin(), file_name.end(), std::back_inserter(*output));
1009*adcb0a62SAndroid Build Coastguard Worker std::copy(extended_field.begin(), extended_field.end(), std::back_inserter(*output));
1010*adcb0a62SAndroid Build Coastguard Worker std::copy(compressed_bytes.begin(), compressed_bytes.end(), std::back_inserter(*output));
1011*adcb0a62SAndroid Build Coastguard Worker std::copy(data_descriptor.begin(), data_descriptor.end(), std::back_inserter(*output));
1012*adcb0a62SAndroid Build Coastguard Worker }
1013*adcb0a62SAndroid Build Coastguard Worker };
1014*adcb0a62SAndroid Build Coastguard Worker
1015*adcb0a62SAndroid Build Coastguard Worker struct CdRecordEntry {
1016*adcb0a62SAndroid Build Coastguard Worker std::vector<uint8_t> central_directory_record;
1017*adcb0a62SAndroid Build Coastguard Worker std::string file_name;
1018*adcb0a62SAndroid Build Coastguard Worker std::vector<uint8_t> extended_field;
1019*adcb0a62SAndroid Build Coastguard Worker
GetSizeZip64ParseTest::CdRecordEntry1020*adcb0a62SAndroid Build Coastguard Worker size_t GetSize() const {
1021*adcb0a62SAndroid Build Coastguard Worker return central_directory_record.size() + file_name.size() + extended_field.size();
1022*adcb0a62SAndroid Build Coastguard Worker }
1023*adcb0a62SAndroid Build Coastguard Worker
CopyToOutputZip64ParseTest::CdRecordEntry1024*adcb0a62SAndroid Build Coastguard Worker void CopyToOutput(std::vector<uint8_t>* output) const {
1025*adcb0a62SAndroid Build Coastguard Worker std::copy(central_directory_record.begin(), central_directory_record.end(),
1026*adcb0a62SAndroid Build Coastguard Worker std::back_inserter(*output));
1027*adcb0a62SAndroid Build Coastguard Worker std::copy(file_name.begin(), file_name.end(), std::back_inserter(*output));
1028*adcb0a62SAndroid Build Coastguard Worker std::copy(extended_field.begin(), extended_field.end(), std::back_inserter(*output));
1029*adcb0a62SAndroid Build Coastguard Worker }
1030*adcb0a62SAndroid Build Coastguard Worker };
1031*adcb0a62SAndroid Build Coastguard Worker
ConstructLocalFileHeader(const std::string & name,std::vector<uint8_t> * output,uint32_t uncompressed_size,uint32_t compressed_size)1032*adcb0a62SAndroid Build Coastguard Worker static void ConstructLocalFileHeader(const std::string& name, std::vector<uint8_t>* output,
1033*adcb0a62SAndroid Build Coastguard Worker uint32_t uncompressed_size, uint32_t compressed_size) {
1034*adcb0a62SAndroid Build Coastguard Worker LocalFileHeader lfh = {};
1035*adcb0a62SAndroid Build Coastguard Worker lfh.lfh_signature = LocalFileHeader::kSignature;
1036*adcb0a62SAndroid Build Coastguard Worker lfh.compressed_size = compressed_size;
1037*adcb0a62SAndroid Build Coastguard Worker lfh.uncompressed_size = uncompressed_size;
1038*adcb0a62SAndroid Build Coastguard Worker lfh.file_name_length = static_cast<uint16_t>(name.size());
1039*adcb0a62SAndroid Build Coastguard Worker lfh.extra_field_length = 20;
1040*adcb0a62SAndroid Build Coastguard Worker *output = std::vector<uint8_t>(reinterpret_cast<uint8_t*>(&lfh),
1041*adcb0a62SAndroid Build Coastguard Worker reinterpret_cast<uint8_t*>(&lfh) + sizeof(LocalFileHeader));
1042*adcb0a62SAndroid Build Coastguard Worker }
1043*adcb0a62SAndroid Build Coastguard Worker
1044*adcb0a62SAndroid Build Coastguard Worker // Put one zip64 extended info in the extended field.
ConstructExtendedField(const std::vector<uint64_t> & zip64_fields,std::vector<uint8_t> * output)1045*adcb0a62SAndroid Build Coastguard Worker static void ConstructExtendedField(const std::vector<uint64_t>& zip64_fields,
1046*adcb0a62SAndroid Build Coastguard Worker std::vector<uint8_t>* output) {
1047*adcb0a62SAndroid Build Coastguard Worker ASSERT_FALSE(zip64_fields.empty());
1048*adcb0a62SAndroid Build Coastguard Worker uint16_t data_size = 8 * static_cast<uint16_t>(zip64_fields.size());
1049*adcb0a62SAndroid Build Coastguard Worker std::vector<uint8_t> extended_field(data_size + 4);
1050*adcb0a62SAndroid Build Coastguard Worker android::base::put_unaligned(extended_field.data(), Zip64ExtendedInfo::kHeaderId);
1051*adcb0a62SAndroid Build Coastguard Worker android::base::put_unaligned(extended_field.data() + 2, data_size);
1052*adcb0a62SAndroid Build Coastguard Worker size_t offset = 4;
1053*adcb0a62SAndroid Build Coastguard Worker for (const auto& field : zip64_fields) {
1054*adcb0a62SAndroid Build Coastguard Worker android::base::put_unaligned(extended_field.data() + offset, field);
1055*adcb0a62SAndroid Build Coastguard Worker offset += 8;
1056*adcb0a62SAndroid Build Coastguard Worker }
1057*adcb0a62SAndroid Build Coastguard Worker
1058*adcb0a62SAndroid Build Coastguard Worker *output = std::move(extended_field);
1059*adcb0a62SAndroid Build Coastguard Worker }
1060*adcb0a62SAndroid Build Coastguard Worker
ConstructCentralDirectoryRecord(const std::string & name,uint32_t uncompressed_size,uint32_t compressed_size,uint32_t local_offset,std::vector<uint8_t> * output)1061*adcb0a62SAndroid Build Coastguard Worker static void ConstructCentralDirectoryRecord(const std::string& name, uint32_t uncompressed_size,
1062*adcb0a62SAndroid Build Coastguard Worker uint32_t compressed_size, uint32_t local_offset,
1063*adcb0a62SAndroid Build Coastguard Worker std::vector<uint8_t>* output) {
1064*adcb0a62SAndroid Build Coastguard Worker CentralDirectoryRecord cdr = {};
1065*adcb0a62SAndroid Build Coastguard Worker cdr.record_signature = CentralDirectoryRecord::kSignature;
1066*adcb0a62SAndroid Build Coastguard Worker cdr.compressed_size = uncompressed_size;
1067*adcb0a62SAndroid Build Coastguard Worker cdr.uncompressed_size = compressed_size;
1068*adcb0a62SAndroid Build Coastguard Worker cdr.file_name_length = static_cast<uint16_t>(name.size());
1069*adcb0a62SAndroid Build Coastguard Worker cdr.extra_field_length = local_offset == UINT32_MAX ? 28 : 20;
1070*adcb0a62SAndroid Build Coastguard Worker cdr.local_file_header_offset = local_offset;
1071*adcb0a62SAndroid Build Coastguard Worker *output =
1072*adcb0a62SAndroid Build Coastguard Worker std::vector<uint8_t>(reinterpret_cast<uint8_t*>(&cdr),
1073*adcb0a62SAndroid Build Coastguard Worker reinterpret_cast<uint8_t*>(&cdr) + sizeof(CentralDirectoryRecord));
1074*adcb0a62SAndroid Build Coastguard Worker }
1075*adcb0a62SAndroid Build Coastguard Worker
1076*adcb0a62SAndroid Build Coastguard Worker // Add an entry to the zipfile, construct the corresponding local header and cd entry.
AddEntry(const std::string & name,const std::vector<uint8_t> & content,bool uncompressed_size_in_extended,bool compressed_size_in_extended,bool local_offset_in_extended,bool include_data_descriptor=false)1077*adcb0a62SAndroid Build Coastguard Worker void AddEntry(const std::string& name, const std::vector<uint8_t>& content,
1078*adcb0a62SAndroid Build Coastguard Worker bool uncompressed_size_in_extended, bool compressed_size_in_extended,
1079*adcb0a62SAndroid Build Coastguard Worker bool local_offset_in_extended, bool include_data_descriptor = false) {
1080*adcb0a62SAndroid Build Coastguard Worker auto uncompressed_size = static_cast<uint32_t>(content.size());
1081*adcb0a62SAndroid Build Coastguard Worker auto compressed_size = static_cast<uint32_t>(content.size());
1082*adcb0a62SAndroid Build Coastguard Worker uint32_t local_file_header_offset = 0;
1083*adcb0a62SAndroid Build Coastguard Worker std::for_each(file_entries_.begin(), file_entries_.end(),
1084*adcb0a62SAndroid Build Coastguard Worker [&local_file_header_offset](const LocalFileEntry& file_entry) {
1085*adcb0a62SAndroid Build Coastguard Worker local_file_header_offset += file_entry.GetSize();
1086*adcb0a62SAndroid Build Coastguard Worker });
1087*adcb0a62SAndroid Build Coastguard Worker
1088*adcb0a62SAndroid Build Coastguard Worker std::vector<uint64_t> zip64_fields;
1089*adcb0a62SAndroid Build Coastguard Worker if (uncompressed_size_in_extended) {
1090*adcb0a62SAndroid Build Coastguard Worker zip64_fields.push_back(uncompressed_size);
1091*adcb0a62SAndroid Build Coastguard Worker uncompressed_size = UINT32_MAX;
1092*adcb0a62SAndroid Build Coastguard Worker }
1093*adcb0a62SAndroid Build Coastguard Worker if (compressed_size_in_extended) {
1094*adcb0a62SAndroid Build Coastguard Worker zip64_fields.push_back(compressed_size);
1095*adcb0a62SAndroid Build Coastguard Worker compressed_size = UINT32_MAX;
1096*adcb0a62SAndroid Build Coastguard Worker }
1097*adcb0a62SAndroid Build Coastguard Worker LocalFileEntry local_entry = {
1098*adcb0a62SAndroid Build Coastguard Worker .local_file_header = {},
1099*adcb0a62SAndroid Build Coastguard Worker .file_name = name,
1100*adcb0a62SAndroid Build Coastguard Worker .extended_field = {},
1101*adcb0a62SAndroid Build Coastguard Worker .compressed_bytes = content,
1102*adcb0a62SAndroid Build Coastguard Worker };
1103*adcb0a62SAndroid Build Coastguard Worker ConstructLocalFileHeader(name, &local_entry.local_file_header, uncompressed_size,
1104*adcb0a62SAndroid Build Coastguard Worker compressed_size);
1105*adcb0a62SAndroid Build Coastguard Worker ConstructExtendedField(zip64_fields, &local_entry.extended_field);
1106*adcb0a62SAndroid Build Coastguard Worker if (include_data_descriptor) {
1107*adcb0a62SAndroid Build Coastguard Worker size_t descriptor_size = compressed_size_in_extended ? 24 : 16;
1108*adcb0a62SAndroid Build Coastguard Worker local_entry.data_descriptor.resize(descriptor_size);
1109*adcb0a62SAndroid Build Coastguard Worker uint8_t* write_ptr = local_entry.data_descriptor.data();
1110*adcb0a62SAndroid Build Coastguard Worker EmitUnaligned<uint32_t>(&write_ptr, DataDescriptor::kOptSignature);
1111*adcb0a62SAndroid Build Coastguard Worker EmitUnaligned<uint32_t>(&write_ptr, 0 /* crc */);
1112*adcb0a62SAndroid Build Coastguard Worker if (compressed_size_in_extended) {
1113*adcb0a62SAndroid Build Coastguard Worker EmitUnaligned<uint64_t>(&write_ptr, compressed_size_in_extended);
1114*adcb0a62SAndroid Build Coastguard Worker EmitUnaligned<uint64_t>(&write_ptr, uncompressed_size_in_extended);
1115*adcb0a62SAndroid Build Coastguard Worker } else {
1116*adcb0a62SAndroid Build Coastguard Worker EmitUnaligned<uint32_t>(&write_ptr, compressed_size_in_extended);
1117*adcb0a62SAndroid Build Coastguard Worker EmitUnaligned<uint32_t>(&write_ptr, uncompressed_size_in_extended);
1118*adcb0a62SAndroid Build Coastguard Worker }
1119*adcb0a62SAndroid Build Coastguard Worker }
1120*adcb0a62SAndroid Build Coastguard Worker
1121*adcb0a62SAndroid Build Coastguard Worker file_entries_.push_back(std::move(local_entry));
1122*adcb0a62SAndroid Build Coastguard Worker
1123*adcb0a62SAndroid Build Coastguard Worker if (local_offset_in_extended) {
1124*adcb0a62SAndroid Build Coastguard Worker zip64_fields.push_back(local_file_header_offset);
1125*adcb0a62SAndroid Build Coastguard Worker local_file_header_offset = UINT32_MAX;
1126*adcb0a62SAndroid Build Coastguard Worker }
1127*adcb0a62SAndroid Build Coastguard Worker CdRecordEntry cd_entry = {
1128*adcb0a62SAndroid Build Coastguard Worker .central_directory_record = {},
1129*adcb0a62SAndroid Build Coastguard Worker .file_name = name,
1130*adcb0a62SAndroid Build Coastguard Worker .extended_field = {},
1131*adcb0a62SAndroid Build Coastguard Worker };
1132*adcb0a62SAndroid Build Coastguard Worker ConstructCentralDirectoryRecord(name, uncompressed_size, compressed_size,
1133*adcb0a62SAndroid Build Coastguard Worker local_file_header_offset, &cd_entry.central_directory_record);
1134*adcb0a62SAndroid Build Coastguard Worker ConstructExtendedField(zip64_fields, &cd_entry.extended_field);
1135*adcb0a62SAndroid Build Coastguard Worker cd_entries_.push_back(std::move(cd_entry));
1136*adcb0a62SAndroid Build Coastguard Worker }
1137*adcb0a62SAndroid Build Coastguard Worker
ConstructEocd()1138*adcb0a62SAndroid Build Coastguard Worker void ConstructEocd() {
1139*adcb0a62SAndroid Build Coastguard Worker ASSERT_EQ(file_entries_.size(), cd_entries_.size());
1140*adcb0a62SAndroid Build Coastguard Worker Zip64EocdRecord zip64_eocd = {};
1141*adcb0a62SAndroid Build Coastguard Worker zip64_eocd.record_signature = Zip64EocdRecord::kSignature;
1142*adcb0a62SAndroid Build Coastguard Worker zip64_eocd.num_records = file_entries_.size();
1143*adcb0a62SAndroid Build Coastguard Worker zip64_eocd.cd_size = 0;
1144*adcb0a62SAndroid Build Coastguard Worker std::for_each(
1145*adcb0a62SAndroid Build Coastguard Worker cd_entries_.begin(), cd_entries_.end(),
1146*adcb0a62SAndroid Build Coastguard Worker [&zip64_eocd](const CdRecordEntry& cd_entry) { zip64_eocd.cd_size += cd_entry.GetSize(); });
1147*adcb0a62SAndroid Build Coastguard Worker zip64_eocd.cd_start_offset = 0;
1148*adcb0a62SAndroid Build Coastguard Worker std::for_each(file_entries_.begin(), file_entries_.end(),
1149*adcb0a62SAndroid Build Coastguard Worker [&zip64_eocd](const LocalFileEntry& file_entry) {
1150*adcb0a62SAndroid Build Coastguard Worker zip64_eocd.cd_start_offset += file_entry.GetSize();
1151*adcb0a62SAndroid Build Coastguard Worker });
1152*adcb0a62SAndroid Build Coastguard Worker zip64_eocd_record_ =
1153*adcb0a62SAndroid Build Coastguard Worker std::vector<uint8_t>(reinterpret_cast<uint8_t*>(&zip64_eocd),
1154*adcb0a62SAndroid Build Coastguard Worker reinterpret_cast<uint8_t*>(&zip64_eocd) + sizeof(Zip64EocdRecord));
1155*adcb0a62SAndroid Build Coastguard Worker
1156*adcb0a62SAndroid Build Coastguard Worker Zip64EocdLocator zip64_locator = {};
1157*adcb0a62SAndroid Build Coastguard Worker zip64_locator.locator_signature = Zip64EocdLocator::kSignature;
1158*adcb0a62SAndroid Build Coastguard Worker zip64_locator.zip64_eocd_offset = zip64_eocd.cd_start_offset + zip64_eocd.cd_size;
1159*adcb0a62SAndroid Build Coastguard Worker zip64_eocd_locator_ =
1160*adcb0a62SAndroid Build Coastguard Worker std::vector<uint8_t>(reinterpret_cast<uint8_t*>(&zip64_locator),
1161*adcb0a62SAndroid Build Coastguard Worker reinterpret_cast<uint8_t*>(&zip64_locator) + sizeof(Zip64EocdLocator));
1162*adcb0a62SAndroid Build Coastguard Worker
1163*adcb0a62SAndroid Build Coastguard Worker EocdRecord eocd = {};
1164*adcb0a62SAndroid Build Coastguard Worker eocd.eocd_signature = EocdRecord::kSignature,
1165*adcb0a62SAndroid Build Coastguard Worker eocd.num_records = file_entries_.size() > UINT16_MAX
1166*adcb0a62SAndroid Build Coastguard Worker ? UINT16_MAX
1167*adcb0a62SAndroid Build Coastguard Worker : static_cast<uint16_t>(file_entries_.size());
1168*adcb0a62SAndroid Build Coastguard Worker eocd.cd_size = UINT32_MAX;
1169*adcb0a62SAndroid Build Coastguard Worker eocd.cd_start_offset = UINT32_MAX;
1170*adcb0a62SAndroid Build Coastguard Worker eocd_record_ = std::vector<uint8_t>(reinterpret_cast<uint8_t*>(&eocd),
1171*adcb0a62SAndroid Build Coastguard Worker reinterpret_cast<uint8_t*>(&eocd) + sizeof(EocdRecord));
1172*adcb0a62SAndroid Build Coastguard Worker }
1173*adcb0a62SAndroid Build Coastguard Worker
1174*adcb0a62SAndroid Build Coastguard Worker // Concatenate all the local file entries, cd entries, and eocd metadata.
ConstructZipFile()1175*adcb0a62SAndroid Build Coastguard Worker void ConstructZipFile() {
1176*adcb0a62SAndroid Build Coastguard Worker for (const auto& file_entry : file_entries_) {
1177*adcb0a62SAndroid Build Coastguard Worker file_entry.CopyToOutput(&zip_content_);
1178*adcb0a62SAndroid Build Coastguard Worker }
1179*adcb0a62SAndroid Build Coastguard Worker for (const auto& cd_entry : cd_entries_) {
1180*adcb0a62SAndroid Build Coastguard Worker cd_entry.CopyToOutput(&zip_content_);
1181*adcb0a62SAndroid Build Coastguard Worker }
1182*adcb0a62SAndroid Build Coastguard Worker std::copy(zip64_eocd_record_.begin(), zip64_eocd_record_.end(),
1183*adcb0a62SAndroid Build Coastguard Worker std::back_inserter(zip_content_));
1184*adcb0a62SAndroid Build Coastguard Worker std::copy(zip64_eocd_locator_.begin(), zip64_eocd_locator_.end(),
1185*adcb0a62SAndroid Build Coastguard Worker std::back_inserter(zip_content_));
1186*adcb0a62SAndroid Build Coastguard Worker std::copy(eocd_record_.begin(), eocd_record_.end(), std::back_inserter(zip_content_));
1187*adcb0a62SAndroid Build Coastguard Worker }
1188*adcb0a62SAndroid Build Coastguard Worker
1189*adcb0a62SAndroid Build Coastguard Worker std::vector<uint8_t> zip_content_;
1190*adcb0a62SAndroid Build Coastguard Worker
1191*adcb0a62SAndroid Build Coastguard Worker std::vector<LocalFileEntry> file_entries_;
1192*adcb0a62SAndroid Build Coastguard Worker std::vector<CdRecordEntry> cd_entries_;
1193*adcb0a62SAndroid Build Coastguard Worker std::vector<uint8_t> zip64_eocd_record_;
1194*adcb0a62SAndroid Build Coastguard Worker std::vector<uint8_t> zip64_eocd_locator_;
1195*adcb0a62SAndroid Build Coastguard Worker std::vector<uint8_t> eocd_record_;
1196*adcb0a62SAndroid Build Coastguard Worker };
1197*adcb0a62SAndroid Build Coastguard Worker
TEST_F(Zip64ParseTest,openFile)1198*adcb0a62SAndroid Build Coastguard Worker TEST_F(Zip64ParseTest, openFile) {
1199*adcb0a62SAndroid Build Coastguard Worker AddEntry("a.txt", std::vector<uint8_t>(100, 'a'), true, true, false);
1200*adcb0a62SAndroid Build Coastguard Worker ConstructEocd();
1201*adcb0a62SAndroid Build Coastguard Worker ConstructZipFile();
1202*adcb0a62SAndroid Build Coastguard Worker
1203*adcb0a62SAndroid Build Coastguard Worker ZipArchiveHandle handle;
1204*adcb0a62SAndroid Build Coastguard Worker ASSERT_EQ(
1205*adcb0a62SAndroid Build Coastguard Worker 0, OpenArchiveFromMemory(zip_content_.data(), zip_content_.size(), "debug_zip64", &handle));
1206*adcb0a62SAndroid Build Coastguard Worker CloseArchive(handle);
1207*adcb0a62SAndroid Build Coastguard Worker }
1208*adcb0a62SAndroid Build Coastguard Worker
TEST_F(Zip64ParseTest,openFilelocalOffsetInExtendedField)1209*adcb0a62SAndroid Build Coastguard Worker TEST_F(Zip64ParseTest, openFilelocalOffsetInExtendedField) {
1210*adcb0a62SAndroid Build Coastguard Worker AddEntry("a.txt", std::vector<uint8_t>(100, 'a'), true, true, true);
1211*adcb0a62SAndroid Build Coastguard Worker AddEntry("b.txt", std::vector<uint8_t>(200, 'b'), true, true, true);
1212*adcb0a62SAndroid Build Coastguard Worker ConstructEocd();
1213*adcb0a62SAndroid Build Coastguard Worker ConstructZipFile();
1214*adcb0a62SAndroid Build Coastguard Worker
1215*adcb0a62SAndroid Build Coastguard Worker ZipArchiveHandle handle;
1216*adcb0a62SAndroid Build Coastguard Worker ASSERT_EQ(
1217*adcb0a62SAndroid Build Coastguard Worker 0, OpenArchiveFromMemory(zip_content_.data(), zip_content_.size(), "debug_zip64", &handle));
1218*adcb0a62SAndroid Build Coastguard Worker CloseArchive(handle);
1219*adcb0a62SAndroid Build Coastguard Worker }
1220*adcb0a62SAndroid Build Coastguard Worker
TEST_F(Zip64ParseTest,openFileCompressedNotInExtendedField)1221*adcb0a62SAndroid Build Coastguard Worker TEST_F(Zip64ParseTest, openFileCompressedNotInExtendedField) {
1222*adcb0a62SAndroid Build Coastguard Worker AddEntry("a.txt", std::vector<uint8_t>(100, 'a'), true, false, false);
1223*adcb0a62SAndroid Build Coastguard Worker ConstructEocd();
1224*adcb0a62SAndroid Build Coastguard Worker ConstructZipFile();
1225*adcb0a62SAndroid Build Coastguard Worker
1226*adcb0a62SAndroid Build Coastguard Worker ZipArchiveHandle handle;
1227*adcb0a62SAndroid Build Coastguard Worker // Zip64 extended fields must include both uncompressed and compressed size.
1228*adcb0a62SAndroid Build Coastguard Worker ASSERT_NE(
1229*adcb0a62SAndroid Build Coastguard Worker 0, OpenArchiveFromMemory(zip_content_.data(), zip_content_.size(), "debug_zip64", &handle));
1230*adcb0a62SAndroid Build Coastguard Worker CloseArchive(handle);
1231*adcb0a62SAndroid Build Coastguard Worker }
1232*adcb0a62SAndroid Build Coastguard Worker
TEST_F(Zip64ParseTest,findEntry)1233*adcb0a62SAndroid Build Coastguard Worker TEST_F(Zip64ParseTest, findEntry) {
1234*adcb0a62SAndroid Build Coastguard Worker AddEntry("a.txt", std::vector<uint8_t>(200, 'a'), true, true, true);
1235*adcb0a62SAndroid Build Coastguard Worker AddEntry("b.txt", std::vector<uint8_t>(300, 'b'), true, true, false);
1236*adcb0a62SAndroid Build Coastguard Worker ConstructEocd();
1237*adcb0a62SAndroid Build Coastguard Worker ConstructZipFile();
1238*adcb0a62SAndroid Build Coastguard Worker
1239*adcb0a62SAndroid Build Coastguard Worker ZipArchiveHandle handle;
1240*adcb0a62SAndroid Build Coastguard Worker ASSERT_EQ(
1241*adcb0a62SAndroid Build Coastguard Worker 0, OpenArchiveFromMemory(zip_content_.data(), zip_content_.size(), "debug_zip64", &handle));
1242*adcb0a62SAndroid Build Coastguard Worker ZipEntry64 entry;
1243*adcb0a62SAndroid Build Coastguard Worker ASSERT_EQ(0, FindEntry(handle, "a.txt", &entry));
1244*adcb0a62SAndroid Build Coastguard Worker ASSERT_EQ(200, entry.uncompressed_length);
1245*adcb0a62SAndroid Build Coastguard Worker ASSERT_EQ(200, entry.compressed_length);
1246*adcb0a62SAndroid Build Coastguard Worker
1247*adcb0a62SAndroid Build Coastguard Worker ASSERT_EQ(0, FindEntry(handle, "b.txt", &entry));
1248*adcb0a62SAndroid Build Coastguard Worker ASSERT_EQ(300, entry.uncompressed_length);
1249*adcb0a62SAndroid Build Coastguard Worker ASSERT_EQ(300, entry.compressed_length);
1250*adcb0a62SAndroid Build Coastguard Worker CloseArchive(handle);
1251*adcb0a62SAndroid Build Coastguard Worker }
1252*adcb0a62SAndroid Build Coastguard Worker
TEST_F(Zip64ParseTest,dataDescriptor)1253*adcb0a62SAndroid Build Coastguard Worker TEST_F(Zip64ParseTest, dataDescriptor) {
1254*adcb0a62SAndroid Build Coastguard Worker AddEntry("a.txt", std::vector<uint8_t>(200, 'a'), true, true, true, false);
1255*adcb0a62SAndroid Build Coastguard Worker AddEntry("b.txt", std::vector<uint8_t>(300, 'b'), true, true, true, false);
1256*adcb0a62SAndroid Build Coastguard Worker // We want a file with compressed size in extended fields, but
1257*adcb0a62SAndroid Build Coastguard Worker // data descriptor still in 32 bit values.
1258*adcb0a62SAndroid Build Coastguard Worker auto& local_entry = file_entries_.back();
1259*adcb0a62SAndroid Build Coastguard Worker local_entry.data_descriptor.resize(16);
1260*adcb0a62SAndroid Build Coastguard Worker uint8_t* write_ptr = local_entry.data_descriptor.data();
1261*adcb0a62SAndroid Build Coastguard Worker EmitUnaligned<uint32_t>(&write_ptr, DataDescriptor::kOptSignature);
1262*adcb0a62SAndroid Build Coastguard Worker EmitUnaligned<uint32_t>(&write_ptr, 0 /* crc */);
1263*adcb0a62SAndroid Build Coastguard Worker EmitUnaligned<uint32_t>(&write_ptr, 300);
1264*adcb0a62SAndroid Build Coastguard Worker EmitUnaligned<uint32_t>(&write_ptr, 300);
1265*adcb0a62SAndroid Build Coastguard Worker
1266*adcb0a62SAndroid Build Coastguard Worker ConstructEocd();
1267*adcb0a62SAndroid Build Coastguard Worker ConstructZipFile();
1268*adcb0a62SAndroid Build Coastguard Worker
1269*adcb0a62SAndroid Build Coastguard Worker ZipArchiveHandle handle;
1270*adcb0a62SAndroid Build Coastguard Worker ASSERT_EQ(0, OpenArchiveFromMemory(zip_content_.data(), zip_content_.size(),
1271*adcb0a62SAndroid Build Coastguard Worker "debug_zip64", &handle));
1272*adcb0a62SAndroid Build Coastguard Worker ZipEntry64 entry;
1273*adcb0a62SAndroid Build Coastguard Worker ASSERT_EQ(0, FindEntry(handle, "a.txt", &entry));
1274*adcb0a62SAndroid Build Coastguard Worker ASSERT_EQ(200, entry.uncompressed_length);
1275*adcb0a62SAndroid Build Coastguard Worker ASSERT_EQ(200, entry.compressed_length);
1276*adcb0a62SAndroid Build Coastguard Worker
1277*adcb0a62SAndroid Build Coastguard Worker ASSERT_EQ(0, FindEntry(handle, "b.txt", &entry));
1278*adcb0a62SAndroid Build Coastguard Worker ASSERT_EQ(300, entry.uncompressed_length);
1279*adcb0a62SAndroid Build Coastguard Worker ASSERT_EQ(300, entry.compressed_length);
1280*adcb0a62SAndroid Build Coastguard Worker CloseArchive(handle);
1281*adcb0a62SAndroid Build Coastguard Worker }
1282*adcb0a62SAndroid Build Coastguard Worker
TEST_F(Zip64ParseTest,openFileIncorrectDataSizeInLocalExtendedField)1283*adcb0a62SAndroid Build Coastguard Worker TEST_F(Zip64ParseTest, openFileIncorrectDataSizeInLocalExtendedField) {
1284*adcb0a62SAndroid Build Coastguard Worker AddEntry("a.txt", std::vector<uint8_t>(100, 'a'), true, true, false);
1285*adcb0a62SAndroid Build Coastguard Worker ASSERT_EQ(1, file_entries_.size());
1286*adcb0a62SAndroid Build Coastguard Worker auto& extended_field = file_entries_[0].extended_field;
1287*adcb0a62SAndroid Build Coastguard Worker // data size exceeds the extended field size in local header.
1288*adcb0a62SAndroid Build Coastguard Worker android::base::put_unaligned<uint16_t>(extended_field.data() + 2, 30);
1289*adcb0a62SAndroid Build Coastguard Worker ConstructEocd();
1290*adcb0a62SAndroid Build Coastguard Worker ConstructZipFile();
1291*adcb0a62SAndroid Build Coastguard Worker
1292*adcb0a62SAndroid Build Coastguard Worker ZipArchiveHandle handle;
1293*adcb0a62SAndroid Build Coastguard Worker ASSERT_EQ(
1294*adcb0a62SAndroid Build Coastguard Worker 0, OpenArchiveFromMemory(zip_content_.data(), zip_content_.size(), "debug_zip64", &handle));
1295*adcb0a62SAndroid Build Coastguard Worker ZipEntry64 entry;
1296*adcb0a62SAndroid Build Coastguard Worker ASSERT_NE(0, FindEntry(handle, "a.txt", &entry));
1297*adcb0a62SAndroid Build Coastguard Worker
1298*adcb0a62SAndroid Build Coastguard Worker CloseArchive(handle);
1299*adcb0a62SAndroid Build Coastguard Worker }
1300*adcb0a62SAndroid Build Coastguard Worker
TEST_F(Zip64ParseTest,iterates)1301*adcb0a62SAndroid Build Coastguard Worker TEST_F(Zip64ParseTest, iterates) {
1302*adcb0a62SAndroid Build Coastguard Worker std::set<std::string_view> names{"a.txt", "b.txt", "c.txt", "d.txt", "e.txt"};
1303*adcb0a62SAndroid Build Coastguard Worker for (const auto& name : names) {
1304*adcb0a62SAndroid Build Coastguard Worker AddEntry(std::string(name), std::vector<uint8_t>(100, name[0]), true, true, true);
1305*adcb0a62SAndroid Build Coastguard Worker }
1306*adcb0a62SAndroid Build Coastguard Worker ConstructEocd();
1307*adcb0a62SAndroid Build Coastguard Worker ConstructZipFile();
1308*adcb0a62SAndroid Build Coastguard Worker
1309*adcb0a62SAndroid Build Coastguard Worker ZipArchiveHandle handle;
1310*adcb0a62SAndroid Build Coastguard Worker ASSERT_EQ(
1311*adcb0a62SAndroid Build Coastguard Worker 0, OpenArchiveFromMemory(zip_content_.data(), zip_content_.size(), "debug_zip64", &handle));
1312*adcb0a62SAndroid Build Coastguard Worker
1313*adcb0a62SAndroid Build Coastguard Worker void* iteration_cookie;
1314*adcb0a62SAndroid Build Coastguard Worker ASSERT_EQ(0, StartIteration(handle, &iteration_cookie));
1315*adcb0a62SAndroid Build Coastguard Worker std::set<std::string_view> result;
1316*adcb0a62SAndroid Build Coastguard Worker std::string_view name;
1317*adcb0a62SAndroid Build Coastguard Worker ZipEntry64 entry;
1318*adcb0a62SAndroid Build Coastguard Worker while (Next(iteration_cookie, &entry, &name) == 0) result.emplace(name);
1319*adcb0a62SAndroid Build Coastguard Worker ASSERT_EQ(names, result);
1320*adcb0a62SAndroid Build Coastguard Worker
1321*adcb0a62SAndroid Build Coastguard Worker CloseArchive(handle);
1322*adcb0a62SAndroid Build Coastguard Worker }
1323*adcb0a62SAndroid Build Coastguard Worker
TEST_F(Zip64ParseTest,zip64EocdWrongLocatorOffset)1324*adcb0a62SAndroid Build Coastguard Worker TEST_F(Zip64ParseTest, zip64EocdWrongLocatorOffset) {
1325*adcb0a62SAndroid Build Coastguard Worker AddEntry("a.txt", std::vector<uint8_t>(1, 'a'), true, true, true);
1326*adcb0a62SAndroid Build Coastguard Worker ConstructEocd();
1327*adcb0a62SAndroid Build Coastguard Worker zip_content_.resize(20, 'a');
1328*adcb0a62SAndroid Build Coastguard Worker std::copy(zip64_eocd_locator_.begin(), zip64_eocd_locator_.end(),
1329*adcb0a62SAndroid Build Coastguard Worker std::back_inserter(zip_content_));
1330*adcb0a62SAndroid Build Coastguard Worker std::copy(eocd_record_.begin(), eocd_record_.end(), std::back_inserter(zip_content_));
1331*adcb0a62SAndroid Build Coastguard Worker
1332*adcb0a62SAndroid Build Coastguard Worker ZipArchiveHandle handle;
1333*adcb0a62SAndroid Build Coastguard Worker ASSERT_NE(
1334*adcb0a62SAndroid Build Coastguard Worker 0, OpenArchiveFromMemory(zip_content_.data(), zip_content_.size(), "debug_zip64", &handle));
1335*adcb0a62SAndroid Build Coastguard Worker CloseArchive(handle);
1336*adcb0a62SAndroid Build Coastguard Worker }
1337*adcb0a62SAndroid Build Coastguard Worker
TEST_F(Zip64ParseTest,extract)1338*adcb0a62SAndroid Build Coastguard Worker TEST_F(Zip64ParseTest, extract) {
1339*adcb0a62SAndroid Build Coastguard Worker std::vector<uint8_t> content(200, 'a');
1340*adcb0a62SAndroid Build Coastguard Worker AddEntry("a.txt", content, true, true, true);
1341*adcb0a62SAndroid Build Coastguard Worker ConstructEocd();
1342*adcb0a62SAndroid Build Coastguard Worker ConstructZipFile();
1343*adcb0a62SAndroid Build Coastguard Worker
1344*adcb0a62SAndroid Build Coastguard Worker ZipArchiveHandle handle;
1345*adcb0a62SAndroid Build Coastguard Worker ASSERT_EQ(
1346*adcb0a62SAndroid Build Coastguard Worker 0, OpenArchiveFromMemory(zip_content_.data(), zip_content_.size(), "debug_zip64", &handle));
1347*adcb0a62SAndroid Build Coastguard Worker ZipEntry64 entry;
1348*adcb0a62SAndroid Build Coastguard Worker ASSERT_EQ(0, FindEntry(handle, "a.txt", &entry));
1349*adcb0a62SAndroid Build Coastguard Worker
1350*adcb0a62SAndroid Build Coastguard Worker VectorWriter writer;
1351*adcb0a62SAndroid Build Coastguard Worker ASSERT_EQ(0, ExtractToWriter(handle, &entry, &writer));
1352*adcb0a62SAndroid Build Coastguard Worker ASSERT_EQ(content, writer.GetOutput());
1353*adcb0a62SAndroid Build Coastguard Worker }
1354*adcb0a62SAndroid Build Coastguard Worker
TEST_F(Zip64ParseTest,extractWithDataDescriptor)1355*adcb0a62SAndroid Build Coastguard Worker TEST_F(Zip64ParseTest, extractWithDataDescriptor) {
1356*adcb0a62SAndroid Build Coastguard Worker std::vector<uint8_t> content(300, 'b');
1357*adcb0a62SAndroid Build Coastguard Worker AddEntry("a.txt", std::vector<uint8_t>(200, 'a'), true, true, true);
1358*adcb0a62SAndroid Build Coastguard Worker AddEntry("b.txt", content, true, true, true, true /* data descriptor */);
1359*adcb0a62SAndroid Build Coastguard Worker ConstructEocd();
1360*adcb0a62SAndroid Build Coastguard Worker ConstructZipFile();
1361*adcb0a62SAndroid Build Coastguard Worker
1362*adcb0a62SAndroid Build Coastguard Worker ZipArchiveHandle handle;
1363*adcb0a62SAndroid Build Coastguard Worker ASSERT_EQ(
1364*adcb0a62SAndroid Build Coastguard Worker 0, OpenArchiveFromMemory(zip_content_.data(), zip_content_.size(), "debug_zip64", &handle));
1365*adcb0a62SAndroid Build Coastguard Worker ZipEntry64 entry;
1366*adcb0a62SAndroid Build Coastguard Worker ASSERT_EQ(0, FindEntry(handle, "b.txt", &entry));
1367*adcb0a62SAndroid Build Coastguard Worker
1368*adcb0a62SAndroid Build Coastguard Worker VectorWriter writer;
1369*adcb0a62SAndroid Build Coastguard Worker ASSERT_EQ(0, ExtractToWriter(handle, &entry, &writer));
1370*adcb0a62SAndroid Build Coastguard Worker ASSERT_EQ(content, writer.GetOutput());
1371*adcb0a62SAndroid Build Coastguard Worker }
1372*adcb0a62SAndroid Build Coastguard Worker
TEST_F(Zip64ParseTest,extraLFHOffset)1373*adcb0a62SAndroid Build Coastguard Worker TEST_F(Zip64ParseTest, extraLFHOffset) {
1374*adcb0a62SAndroid Build Coastguard Worker std::vector<uint8_t> content(300, 'b');
1375*adcb0a62SAndroid Build Coastguard Worker AddEntry("a.txt", std::vector<uint8_t>(200, 'a'), true, true, true);
1376*adcb0a62SAndroid Build Coastguard Worker AddEntry("b.txt", content, true, true, true, true /* data descriptor */);
1377*adcb0a62SAndroid Build Coastguard Worker
1378*adcb0a62SAndroid Build Coastguard Worker ASSERT_EQ(cd_entries_.back().extended_field.size(), 4 + 8 * 3)
1379*adcb0a62SAndroid Build Coastguard Worker << "Extended field should contain 2 bytes id, 2 bytes size, and 3 "
1380*adcb0a62SAndroid Build Coastguard Worker "values, each 64 bit";
1381*adcb0a62SAndroid Build Coastguard Worker uint32_t local_file_header_offset = 0;
1382*adcb0a62SAndroid Build Coastguard Worker std::for_each(file_entries_.begin(), file_entries_.end() - 1,
1383*adcb0a62SAndroid Build Coastguard Worker [&local_file_header_offset](const LocalFileEntry& file_entry) {
1384*adcb0a62SAndroid Build Coastguard Worker local_file_header_offset += file_entry.GetSize();
1385*adcb0a62SAndroid Build Coastguard Worker });
1386*adcb0a62SAndroid Build Coastguard Worker auto& cd_entry = cd_entries_.back();
1387*adcb0a62SAndroid Build Coastguard Worker // We want to construct a central directory record with LFH < 0xFFFFFFFF
1388*adcb0a62SAndroid Build Coastguard Worker // but still comes with a 64 bit LFH in extended field.
1389*adcb0a62SAndroid Build Coastguard Worker ConstructCentralDirectoryRecord(
1390*adcb0a62SAndroid Build Coastguard Worker "b.txt", static_cast<uint32_t>(content.size()),
1391*adcb0a62SAndroid Build Coastguard Worker static_cast<uint32_t>(content.size()), local_file_header_offset,
1392*adcb0a62SAndroid Build Coastguard Worker &cd_entry.central_directory_record);
1393*adcb0a62SAndroid Build Coastguard Worker ConstructEocd();
1394*adcb0a62SAndroid Build Coastguard Worker ConstructZipFile();
1395*adcb0a62SAndroid Build Coastguard Worker
1396*adcb0a62SAndroid Build Coastguard Worker ZipArchiveHandle handle;
1397*adcb0a62SAndroid Build Coastguard Worker ASSERT_EQ(0, OpenArchiveFromMemory(zip_content_.data(), zip_content_.size(),
1398*adcb0a62SAndroid Build Coastguard Worker "debug_zip64", &handle));
1399*adcb0a62SAndroid Build Coastguard Worker ZipEntry64 entry;
1400*adcb0a62SAndroid Build Coastguard Worker ASSERT_EQ(0, FindEntry(handle, "b.txt", &entry));
1401*adcb0a62SAndroid Build Coastguard Worker
1402*adcb0a62SAndroid Build Coastguard Worker VectorWriter writer;
1403*adcb0a62SAndroid Build Coastguard Worker ASSERT_EQ(0, ExtractToWriter(handle, &entry, &writer));
1404*adcb0a62SAndroid Build Coastguard Worker ASSERT_EQ(content, writer.GetOutput());
1405*adcb0a62SAndroid Build Coastguard Worker }
1406*adcb0a62SAndroid Build Coastguard Worker
TEST(ziparchive,Bug174945959)1407*adcb0a62SAndroid Build Coastguard Worker TEST(ziparchive, Bug174945959) {
1408*adcb0a62SAndroid Build Coastguard Worker static const std::vector<uint8_t> zip {
1409*adcb0a62SAndroid Build Coastguard Worker 0x50, 0x4b, 0x03, 0x04, 0x50, 0x4b, 0x01, 0x02, 0x01, 0x53, 0x46, 0x5b,
1410*adcb0a62SAndroid Build Coastguard Worker 0xa4, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x7f, 0xff, 0xff,
1411*adcb0a62SAndroid Build Coastguard Worker 0xff, 0xff, 0xff, 0xff, 0x03, 0x12, 0x00, 0x07, 0x00, 0x00, 0x3b, 0x00,
1412*adcb0a62SAndroid Build Coastguard Worker 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xeb, 0x00, 0x00, 0x00, 0x00,
1413*adcb0a62SAndroid Build Coastguard Worker 0x00, 0x00, 0x01, 0x00, 0x18, 0x00, 0x00, 0xa4, 0x2e, 0x00, 0x00, 0x00,
1414*adcb0a62SAndroid Build Coastguard Worker 0x24, 0x24, 0xb6, 0x3f, 0xff, 0xff, 0x31, 0x51, 0x49, 0xff, 0xff, 0xff,
1415*adcb0a62SAndroid Build Coastguard Worker 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1416*adcb0a62SAndroid Build Coastguard Worker 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1417*adcb0a62SAndroid Build Coastguard Worker 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1418*adcb0a62SAndroid Build Coastguard Worker 0x4b, 0x05, 0x50, 0x4b, 0x05, 0x06, 0xc5, 0x1f, 0x4a, 0x04, 0x00, 0x21,
1419*adcb0a62SAndroid Build Coastguard Worker 0x01, 0x00, 0x6a, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00};
1420*adcb0a62SAndroid Build Coastguard Worker ZipArchiveHandle handle;
1421*adcb0a62SAndroid Build Coastguard Worker ASSERT_EQ(0, OpenArchiveFromMemory(&zip[0], zip.size(), "name", &handle));
1422*adcb0a62SAndroid Build Coastguard Worker
1423*adcb0a62SAndroid Build Coastguard Worker void* cookie;
1424*adcb0a62SAndroid Build Coastguard Worker ASSERT_EQ(0, StartIteration(handle, &cookie));
1425*adcb0a62SAndroid Build Coastguard Worker ZipEntry ze;
1426*adcb0a62SAndroid Build Coastguard Worker std::string name;
1427*adcb0a62SAndroid Build Coastguard Worker int result;
1428*adcb0a62SAndroid Build Coastguard Worker while ((result = Next(cookie, &ze, &name)) == 0) {
1429*adcb0a62SAndroid Build Coastguard Worker }
1430*adcb0a62SAndroid Build Coastguard Worker EndIteration(cookie);
1431*adcb0a62SAndroid Build Coastguard Worker }
1432