1 /*
2  * Copyright (c) 2021-2022 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "zip_archive.h"
17 #include "libpandafile/file.h"
18 #include "os/file.h"
19 #include "os/mem.h"
20 
21 #include "assembly-emitter.h"
22 #include "assembly-parser.h"
23 
24 #include <cstddef>
25 #include <cstdio>
26 #include <cstdint>
27 #include <vector>
28 #include <gtest/gtest.h>
29 #include <memory>
30 #include <securec.h>
31 
32 #include <climits>
33 #include <cstdlib>
34 #include <sys/stat.h>
35 #include <fcntl.h>
36 #include <sys/stat.h>
37 
38 namespace panda::test {
39 
40 #define GTEST_COUT std::cerr << "[          ] [ INFO ]"
41 
42 constexpr size_t MAX_BUFFER_SIZE = 2048;
43 constexpr size_t MAX_DIR_SIZE = 64;
44 
GenerateZipfile(const char *data, const char *archivename, int N, char *buf, char *archive_filename, int &i, int &ret, std::vector<uint8_t> &pf_data, int level = Z_BEST_COMPRESSION)45 static void GenerateZipfile(const char *data, const char *archivename, int N, char *buf, char *archive_filename, int &i,
46                             int &ret, std::vector<uint8_t> &pf_data, int level = Z_BEST_COMPRESSION)
47 {
48     // Delete the test archive, so it doesn't keep growing as we run this test
49     remove(archivename);
50 
51     // Create and append a directory entry for testing
52     ret = CreateOrAddFileIntoZip(archivename, "directory/", NULL, 0, APPEND_STATUS_CREATE, level);
53     if (ret != 0) {
54         ASSERT_EQ(1, 0) << "CreateOrAddFileIntoZip for directory failed!";
55         return;
56     }
57 
58     // Append a bunch of text files to the test archive
59     for (i = (N - 1); i >= 0; --i) {
60         (void)sprintf_s(archive_filename, MAX_DIR_SIZE, "%d.txt", i);
61         (void)sprintf_s(buf, MAX_BUFFER_SIZE, "%d %s %d", (N - 1) - i, data, i);
62         ret =
63             CreateOrAddFileIntoZip(archivename, archive_filename, buf, strlen(buf) + 1, APPEND_STATUS_ADDINZIP, level);
64         if (ret != 0) {
65             ASSERT_EQ(1, 0) << "CreateOrAddFileIntoZip for " << i << ".txt failed!";
66             return;
67         }
68     }
69 
70     // Append a file into directory entry for testing
71     (void)sprintf_s(buf, MAX_BUFFER_SIZE, "%d %s %d", N, data, N);
72     ret = CreateOrAddFileIntoZip(archivename, "directory/indirectory.txt", buf, strlen(buf) + 1, APPEND_STATUS_ADDINZIP,
73                                  level);
74     if (ret != 0) {
75         ASSERT_EQ(1, 0) << "CreateOrAddFileIntoZip for directory/indirectory.txt failed!";
76         return;
77     }
78 
79     // Add a pandafile into zip for testing
80     ret = CreateOrAddFileIntoZip(archivename, "classes.abc", pf_data.data(), pf_data.size(), APPEND_STATUS_ADDINZIP,
81                                  level);
82     if (ret != 0) {
83         ASSERT_EQ(1, 0) << "CreateOrAddFileIntoZip for classes.abc failed!";
84         return;
85     }
86 }
87 
UnzipFileCheckDirectory(const char *archivename, char *filename, int level = Z_BEST_COMPRESSION)88 static void UnzipFileCheckDirectory(const char *archivename, char *filename, int level = Z_BEST_COMPRESSION)
89 {
90     (void)sprintf_s(filename, MAX_DIR_SIZE, "directory/");
91 
92     ZipArchiveHandle zipfile = nullptr;
93     FILE *myfile = fopen(archivename, "rbe");
94 
95     if (OpenArchiveFile(zipfile, myfile) != 0) {
96         fclose(myfile);
97         ASSERT_EQ(1, 0) << "OpenArchiveFILE error.";
98         return;
99     }
100     if (LocateFile(zipfile, filename) != 0) {
101         CloseArchiveFile(zipfile);
102         fclose(myfile);
103         ASSERT_EQ(1, 0) << "LocateFile error.";
104         return;
105     }
106     EntryFileStat entry = EntryFileStat();
107     if (GetCurrentFileInfo(zipfile, &entry) != 0) {
108         CloseArchiveFile(zipfile);
109         fclose(myfile);
110         ASSERT_EQ(1, 0) << "GetCurrentFileInfo test error.";
111         return;
112     }
113     if (OpenCurrentFile(zipfile) != 0) {
114         CloseCurrentFile(zipfile);
115         CloseArchiveFile(zipfile);
116         fclose(myfile);
117         ASSERT_EQ(1, 0) << "OpenCurrentFile test error.";
118         return;
119     }
120 
121     GetCurrentFileOffset(zipfile, &entry);
122 
123     uint32_t uncompressed_length = entry.GetUncompressedSize();
124 
125     ASSERT_GT(entry.GetOffset(), 0U);
126     if (level == Z_NO_COMPRESSION) {
127         ASSERT_FALSE(entry.IsCompressed());
128     } else {
129         ASSERT_TRUE(entry.IsCompressed());
130     }
131 
132     GTEST_COUT << "Filename: " << filename << ", Uncompressed size: " << uncompressed_length
133                << "Compressed size: " << entry.GetCompressedSize() << "Compressed(): " << entry.IsCompressed()
134                << "entry offset: " << entry.GetOffset() << "\n";
135 
136     CloseCurrentFile(zipfile);
137     CloseArchiveFile(zipfile);
138     fclose(myfile);
139 }
140 
UnzipFileCheckTxt(const char *archivename, char *filename, const char *data, int N, char *buf, int &ret, int level = Z_BEST_COMPRESSION)141 static void UnzipFileCheckTxt(const char *archivename, char *filename, const char *data, int N, char *buf, int &ret,
142                               int level = Z_BEST_COMPRESSION)
143 {
144     for (int i = 0; i < N; i++) {
145         (void)sprintf_s(filename, MAX_DIR_SIZE, "%d.txt", i);
146         (void)sprintf_s(buf, MAX_BUFFER_SIZE, "%d %s %d", (N - 1) - i, data, i);
147 
148         ZipArchiveHandle zipfile = nullptr;
149         FILE *myfile = fopen(archivename, "rbe");
150 
151         if (OpenArchiveFile(zipfile, myfile) != 0) {
152             fclose(myfile);
153             ASSERT_EQ(1, 0) << "OpenArchiveFILE error.";
154             return;
155         }
156         if (LocateFile(zipfile, filename) != 0) {
157             CloseArchiveFile(zipfile);
158             fclose(myfile);
159             ASSERT_EQ(1, 0) << "LocateFile error.";
160             return;
161         }
162         EntryFileStat entry = EntryFileStat();
163         if (GetCurrentFileInfo(zipfile, &entry) != 0) {
164             CloseArchiveFile(zipfile);
165             fclose(myfile);
166             ASSERT_EQ(1, 0) << "GetCurrentFileInfo test error.";
167             return;
168         }
169         if (OpenCurrentFile(zipfile) != 0) {
170             CloseCurrentFile(zipfile);
171             CloseArchiveFile(zipfile);
172             fclose(myfile);
173             ASSERT_EQ(1, 0) << "OpenCurrentFile test error.";
174             return;
175         }
176 
177         GetCurrentFileOffset(zipfile, &entry);
178 
179         uint32_t uncompressed_length = entry.GetUncompressedSize();
180         if (uncompressed_length == 0) {
181             CloseCurrentFile(zipfile);
182             CloseArchiveFile(zipfile);
183             fclose(myfile);
184             ASSERT_EQ(1, 0) << "Entry file has zero length! Readed bad data!";
185             return;
186         }
187         ASSERT_GT(entry.GetOffset(), 0U);
188         ASSERT_EQ(uncompressed_length, strlen(buf) + 1);
189         if (level == Z_NO_COMPRESSION) {
190             ASSERT_EQ(uncompressed_length, entry.GetCompressedSize());
191             ASSERT_FALSE(entry.IsCompressed());
192         } else {
193             ASSERT_GE(uncompressed_length, entry.GetCompressedSize());
194             ASSERT_TRUE(entry.IsCompressed());
195         }
196 
197         GTEST_COUT << "Filename: " << filename << ", Uncompressed size: " << uncompressed_length
198                    << "Compressed size: " << entry.GetCompressedSize() << "Compressed(): " << entry.IsCompressed()
199                    << "entry offset: " << entry.GetOffset() << "\n";
200 
201         {
202             // Extract to mem buffer accroding to entry info.
203             uint32_t page_size = os::mem::GetPageSize();
204             uint32_t min_pages = uncompressed_length / page_size;
205             uint32_t size_to_mmap =
206                 uncompressed_length % page_size == 0 ? min_pages * page_size : (min_pages + 1) * page_size;
207             // we will use mem in memcmp, so donnot poision it!
208             void *mem = os::mem::MapRWAnonymousRaw(size_to_mmap, false);
209             if (mem == nullptr) {
210                 CloseCurrentFile(zipfile);
211                 CloseArchiveFile(zipfile);
212                 fclose(myfile);
213                 ASSERT_EQ(1, 0) << "Can't mmap anonymous!";
214                 return;
215             }
216 
217             ret = ExtractToMemory(zipfile, reinterpret_cast<uint8_t *>(mem), size_to_mmap);
218             if (ret != 0) {
219                 os::mem::UnmapRaw(mem, size_to_mmap);
220                 CloseCurrentFile(zipfile);
221                 CloseArchiveFile(zipfile);
222                 fclose(myfile);
223                 ASSERT_EQ(1, 0) << "Can't extract!";
224                 return;
225             }
226 
227             // Make sure the extraction really succeeded.
228             size_t dlen = strlen(buf);
229             if (uncompressed_length != (dlen + 1)) {
230                 os::mem::UnmapRaw(mem, size_to_mmap);
231                 CloseCurrentFile(zipfile);
232                 CloseArchive(zipfile);
233                 fclose(myfile);
234                 ASSERT_EQ(1, 0) << "ExtractToMemory() failed!, uncompressed_length is " << uncompressed_length - 1
235                                 << ", original strlen is " << dlen;
236                 return;
237             }
238 
239             if (memcmp(mem, buf, dlen)) {
240                 os::mem::UnmapRaw(mem, size_to_mmap);
241                 CloseCurrentFile(zipfile);
242                 CloseArchive(zipfile);
243                 fclose(myfile);
244                 ASSERT_EQ(1, 0) << "ExtractToMemory() memcmp failed!";
245                 return;
246             }
247 
248             GTEST_COUT << "Successfully extracted file " << filename << " from " << archivename << ", size is "
249                        << uncompressed_length << "\n";
250             os::mem::UnmapRaw(mem, size_to_mmap);
251         }
252 
253         CloseCurrentFile(zipfile);
254         CloseArchiveFile(zipfile);
255         fclose(myfile);
256     }
257 }
258 
UnzipFileCheckPandaFile(const char *archivename, char *filename, std::vector<uint8_t> &pf_data, int &ret, int level = Z_BEST_COMPRESSION)259 static void UnzipFileCheckPandaFile(const char *archivename, char *filename, std::vector<uint8_t> &pf_data, int &ret,
260                                     int level = Z_BEST_COMPRESSION)
261 {
262     {
263         ZipArchiveHandle zipfile = nullptr;
264         FILE *myfile = fopen(archivename, "rbe");
265 
266         if (OpenArchiveFile(zipfile, myfile) != 0) {
267             fclose(myfile);
268             ASSERT_EQ(1, 0) << "OpenArchiveFILE error.";
269             return;
270         }
271         if (LocateFile(zipfile, filename) != 0) {
272             CloseArchiveFile(zipfile);
273             fclose(myfile);
274             ASSERT_EQ(1, 0) << "LocateFile error.";
275             return;
276         }
277         EntryFileStat entry = EntryFileStat();
278         if (GetCurrentFileInfo(zipfile, &entry) != 0) {
279             CloseArchiveFile(zipfile);
280             fclose(myfile);
281             ASSERT_EQ(1, 0) << "GetCurrentFileInfo test error.";
282             return;
283         }
284         if (OpenCurrentFile(zipfile) != 0) {
285             CloseCurrentFile(zipfile);
286             CloseArchiveFile(zipfile);
287             fclose(myfile);
288             ASSERT_EQ(1, 0) << "OpenCurrentFile test error.";
289             return;
290         }
291 
292         GetCurrentFileOffset(zipfile, &entry);
293 
294         uint32_t uncompressed_length = entry.GetUncompressedSize();
295         if (uncompressed_length == 0) {
296             CloseCurrentFile(zipfile);
297             CloseArchiveFile(zipfile);
298             fclose(myfile);
299             ASSERT_EQ(1, 0) << "Entry file has zero length! Readed bad data!";
300             return;
301         }
302         ASSERT_GT(entry.GetOffset(), 0U);
303         ASSERT_EQ(uncompressed_length, pf_data.size());
304         if (level == Z_NO_COMPRESSION) {
305             ASSERT_EQ(uncompressed_length, entry.GetCompressedSize());
306             ASSERT_FALSE(entry.IsCompressed());
307         } else {
308             ASSERT_GE(uncompressed_length, entry.GetCompressedSize());
309             ASSERT_TRUE(entry.IsCompressed());
310         }
311 
312         GTEST_COUT << "Filename: " << filename << ", Uncompressed size: " << uncompressed_length
313                    << "Compressed size: " << entry.GetCompressedSize() << "Compressed(): " << entry.IsCompressed()
314                    << "entry offset: " << entry.GetOffset() << "\n";
315 
316         {
317             // Extract to mem buffer accroding to entry info.
318             uint32_t page_size = os::mem::GetPageSize();
319             uint32_t min_pages = uncompressed_length / page_size;
320             uint32_t size_to_mmap =
321                 uncompressed_length % page_size == 0 ? min_pages * page_size : (min_pages + 1) * page_size;
322             // we will use mem in memcmp, so donnot poision it!
323             void *mem = os::mem::MapRWAnonymousRaw(size_to_mmap, false);
324             if (mem == nullptr) {
325                 CloseCurrentFile(zipfile);
326                 CloseArchiveFile(zipfile);
327                 fclose(myfile);
328                 ASSERT_EQ(1, 0) << "Can't mmap anonymous!";
329                 return;
330             }
331 
332             ret = ExtractToMemory(zipfile, reinterpret_cast<uint8_t *>(mem), size_to_mmap);
333             if (ret != 0) {
334                 os::mem::UnmapRaw(mem, size_to_mmap);
335                 CloseCurrentFile(zipfile);
336                 CloseArchiveFile(zipfile);
337                 fclose(myfile);
338                 ASSERT_EQ(1, 0) << "Can't extract!";
339                 return;
340             }
341 
342             // Make sure the extraction really succeeded.
343             if (uncompressed_length != pf_data.size()) {
344                 os::mem::UnmapRaw(mem, size_to_mmap);
345                 CloseCurrentFile(zipfile);
346                 CloseArchiveFile(zipfile);
347                 fclose(myfile);
348                 ASSERT_EQ(1, 0) << "ExtractToMemory() failed!, uncompressed_length is " << uncompressed_length
349                                 << ", original pf_data size is " << pf_data.size() << "\n";
350                 return;
351             }
352 
353             if (memcmp(mem, pf_data.data(), pf_data.size())) {
354                 os::mem::UnmapRaw(mem, size_to_mmap);
355                 CloseCurrentFile(zipfile);
356                 CloseArchiveFile(zipfile);
357                 fclose(myfile);
358                 ASSERT_EQ(1, 0) << "ExtractToMemory() memcmp failed!";
359                 return;
360             }
361 
362             GTEST_COUT << "Successfully extracted file " << filename << " from " << archivename << ", size is "
363                        << uncompressed_length << "\n";
364 
365             os::mem::UnmapRaw(mem, size_to_mmap);
366         }
367         CloseCurrentFile(zipfile);
368         CloseArchiveFile(zipfile);
369         fclose(myfile);
370     }
371 }
372 
UnzipFileCheckInDirectory(const char *archivename, char *filename, const char *data, int N, char *buf, int &ret, int level = Z_BEST_COMPRESSION)373 static void UnzipFileCheckInDirectory(const char *archivename, char *filename, const char *data, int N, char *buf,
374                                       int &ret, int level = Z_BEST_COMPRESSION)
375 {
376     {
377         (void)sprintf_s(filename, MAX_DIR_SIZE, "directory/indirectory.txt");
378         (void)sprintf_s(buf, MAX_BUFFER_SIZE, "%d %s %d", N, data, N);
379 
380         // Unzip Check
381         ZipArchiveHandle zipfile = nullptr;
382         FILE *myfile = fopen(archivename, "rbe");
383 
384         if (OpenArchiveFile(zipfile, myfile) != 0) {
385             fclose(myfile);
386             ASSERT_EQ(1, 0) << "OpenArchiveFILE error.";
387             return;
388         }
389         if (LocateFile(zipfile, filename) != 0) {
390             CloseArchiveFile(zipfile);
391             fclose(myfile);
392             ASSERT_EQ(1, 0) << "LocateFile error.";
393             return;
394         }
395         EntryFileStat entry = EntryFileStat();
396         if (GetCurrentFileInfo(zipfile, &entry) != 0) {
397             CloseArchiveFile(zipfile);
398             fclose(myfile);
399             ASSERT_EQ(1, 0) << "GetCurrentFileInfo test error.";
400             return;
401         }
402         if (OpenCurrentFile(zipfile) != 0) {
403             CloseCurrentFile(zipfile);
404             CloseArchiveFile(zipfile);
405             fclose(myfile);
406             ASSERT_EQ(1, 0) << "OpenCurrentFile test error.";
407             return;
408         }
409 
410         GetCurrentFileOffset(zipfile, &entry);
411 
412         uint32_t uncompressed_length = entry.GetUncompressedSize();
413         if (uncompressed_length == 0) {
414             CloseCurrentFile(zipfile);
415             CloseArchiveFile(zipfile);
416             fclose(myfile);
417             ASSERT_EQ(1, 0) << "Entry file has zero length! Readed bad data!";
418             return;
419         }
420         ASSERT_GT(entry.GetOffset(), 0U);
421         ASSERT_EQ(uncompressed_length, strlen(buf) + 1);
422         if (level == Z_NO_COMPRESSION) {
423             ASSERT_EQ(uncompressed_length, entry.GetCompressedSize());
424             ASSERT_FALSE(entry.IsCompressed());
425         } else {
426             ASSERT_GE(uncompressed_length, entry.GetCompressedSize());
427             ASSERT_TRUE(entry.IsCompressed());
428         }
429         GTEST_COUT << "Filename: " << filename << ", Uncompressed size: " << uncompressed_length
430                    << "Compressed size: " << entry.GetCompressedSize() << "Compressed(): " << entry.IsCompressed()
431                    << "entry offset: " << entry.GetOffset() << "\n";
432 
433         {
434             // Extract to mem buffer accroding to entry info.
435             uint32_t page_size = os::mem::GetPageSize();
436             uint32_t min_pages = uncompressed_length / page_size;
437             uint32_t size_to_mmap =
438                 uncompressed_length % page_size == 0 ? min_pages * page_size : (min_pages + 1) * page_size;
439             // we will use mem in memcmp, so donnot poision it!
440             void *mem = os::mem::MapRWAnonymousRaw(size_to_mmap, false);
441             if (mem == nullptr) {
442                 CloseCurrentFile(zipfile);
443                 CloseArchiveFile(zipfile);
444                 fclose(myfile);
445                 ASSERT_EQ(1, 0) << "Can't mmap anonymous!";
446                 return;
447             }
448 
449             ret = ExtractToMemory(zipfile, reinterpret_cast<uint8_t *>(mem), size_to_mmap);
450             if (ret != 0) {
451                 os::mem::UnmapRaw(mem, size_to_mmap);
452                 CloseCurrentFile(zipfile);
453                 CloseArchiveFile(zipfile);
454                 fclose(myfile);
455                 ASSERT_EQ(1, 0) << "Can't extract!";
456                 return;
457             }
458 
459             // Make sure the extraction really succeeded.
460             size_t dlen = strlen(buf);
461             if (uncompressed_length != (dlen + 1)) {
462                 os::mem::UnmapRaw(mem, size_to_mmap);
463                 CloseCurrentFile(zipfile);
464                 CloseArchive(zipfile);
465                 fclose(myfile);
466                 ASSERT_EQ(1, 0) << "ExtractToMemory() failed!, uncompressed_length is " << uncompressed_length - 1
467                                 << ", original strlen is " << dlen;
468                 return;
469             }
470 
471             if (memcmp(mem, buf, dlen)) {
472                 os::mem::UnmapRaw(mem, size_to_mmap);
473                 CloseCurrentFile(zipfile);
474                 CloseArchive(zipfile);
475                 fclose(myfile);
476                 ASSERT_EQ(1, 0) << "ExtractToMemory() memcmp failed!";
477                 return;
478             }
479 
480             GTEST_COUT << "Successfully extracted file " << filename << " from " << archivename << ", size is "
481                        << uncompressed_length << "\n";
482 
483             os::mem::UnmapRaw(mem, size_to_mmap);
484         }
485 
486         CloseCurrentFile(zipfile);
487         CloseArchiveFile(zipfile);
488         fclose(myfile);
489     }
490 }
491 
HWTEST(LIBZIPARCHIVE, ZipFile, testing::ext::TestSize.Level0)492 HWTEST(LIBZIPARCHIVE, ZipFile, testing::ext::TestSize.Level0)
493 {
494     static const char *data =
495         "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras feugiat et odio ac sollicitudin. Maecenas "
496         "lobortis ultrices eros sed pharetra. Phasellus in tortor rhoncus, aliquam augue ac, gravida elit. Sed "
497         "molestie dolor a vulputate tincidunt. Proin a tellus quam. Suspendisse id feugiat elit, non ornare lacus. "
498         "Mauris arcu ex, pretium quis dolor ut, porta iaculis eros. Vestibulum sagittis placerat diam, vitae efficitur "
499         "turpis ultrices sit amet. Etiam elementum bibendum congue. In sit amet dolor ultricies, suscipit arcu ac, "
500         "molestie urna. Mauris ultrices volutpat massa quis ultrices. Suspendisse rutrum lectus sit amet metus "
501         "laoreet, non porta sapien venenatis. Fusce ut massa et purus elementum lacinia. Sed tempus bibendum pretium.";
502 
503     /*
504      * creating an empty pandafile
505      */
506     std::vector<uint8_t> pf_data {};
507     {
508         pandasm::Parser p;
509 
510         auto source = R"()";
511 
512         std::string src_filename = "src.pa";
513         auto res = p.Parse(source, src_filename);
514         ASSERT_EQ(p.ShowError().err, pandasm::Error::ErrorType::ERR_NONE);
515 
516         auto pf = pandasm::AsmEmitter::Emit(res.Value());
517         ASSERT_NE(pf, nullptr);
518 
519         const auto header_ptr = reinterpret_cast<const uint8_t *>(pf->GetHeader());
520         pf_data.assign(header_ptr, header_ptr + sizeof(panda_file::File::Header));
521     }
522 
523     static const char *archivename = "__LIBZIPARCHIVE__ZipFile__.zip";
524     const int N = 3;
525     char buf[MAX_BUFFER_SIZE];
526     char archive_filename[MAX_DIR_SIZE];
527     int i = 0;
528     int ret = 0;
529 
530     GenerateZipfile(data, archivename, N, buf, archive_filename, i, ret, pf_data);
531 
532     // Quick Check
533     ZipArchiveHandle zipfile = nullptr;
534     if (OpenArchive(zipfile, archivename) != 0) {
535         ASSERT_EQ(1, 0) << "OpenArchive error.";
536         return;
537     }
538 
539     GlobalStat gi = GlobalStat();
540     if (GetGlobalFileInfo(zipfile, &gi) != 0) {
541         ASSERT_EQ(1, 0) << "GetGlobalFileInfo error.";
542         return;
543     }
544     for (i = 0; i < (int)gi.GetNumberOfEntry(); ++i) {
545         EntryFileStat file_stat;
546         if (GetCurrentFileInfo(zipfile, &file_stat) != 0) {
547             CloseArchive(zipfile);
548             ASSERT_EQ(1, 0) << "GetCurrentFileInfo error. Current index i = " << i;
549             return;
550         }
551         GTEST_COUT << "Index:  " << i << ", Uncompressed size: " << file_stat.GetUncompressedSize()
552                    << "Compressed size: " << file_stat.GetCompressedSize()
553                    << "Compressed(): " << file_stat.IsCompressed() << "entry offset: " << file_stat.GetOffset() << "\n";
554         if ((i + 1) < (int)gi.GetNumberOfEntry()) {
555             if (GoToNextFile(zipfile) != 0) {
556                 CloseArchive(zipfile);
557                 ASSERT_EQ(1, 0) << "GoToNextFile error. Current index i = " << i;
558                 return;
559             }
560         }
561     }
562 
563     CloseArchive(zipfile);
564     remove(archivename);
565     GTEST_COUT << "Success.\n";
566 }
567 
HWTEST(LIBZIPARCHIVE, UnZipFile, testing::ext::TestSize.Level0)568 HWTEST(LIBZIPARCHIVE, UnZipFile, testing::ext::TestSize.Level0)
569 {
570     static const char *data =
571         "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras feugiat et odio ac sollicitudin. Maecenas "
572         "lobortis ultrices eros sed pharetra. Phasellus in tortor rhoncus, aliquam augue ac, gravida elit. Sed "
573         "molestie dolor a vulputate tincidunt. Proin a tellus quam. Suspendisse id feugiat elit, non ornare lacus. "
574         "Mauris arcu ex, pretium quis dolor ut, porta iaculis eros. Vestibulum sagittis placerat diam, vitae efficitur "
575         "turpis ultrices sit amet. Etiam elementum bibendum congue. In sit amet dolor ultricies, suscipit arcu ac, "
576         "molestie urna. Mauris ultrices volutpat massa quis ultrices. Suspendisse rutrum lectus sit amet metus "
577         "laoreet, non porta sapien venenatis. Fusce ut massa et purus elementum lacinia. Sed tempus bibendum pretium.";
578 
579     /*
580      * creating an empty pandafile
581      */
582     std::vector<uint8_t> pf_data {};
583     {
584         pandasm::Parser p;
585 
586         auto source = R"()";
587 
588         std::string src_filename = "src.pa";
589         auto res = p.Parse(source, src_filename);
590         ASSERT_EQ(p.ShowError().err, pandasm::Error::ErrorType::ERR_NONE);
591 
592         auto pf = pandasm::AsmEmitter::Emit(res.Value());
593         ASSERT_NE(pf, nullptr);
594 
595         const auto header_ptr = reinterpret_cast<const uint8_t *>(pf->GetHeader());
596         pf_data.assign(header_ptr, header_ptr + sizeof(panda_file::File::Header));
597     }
598 
599     // The zip filename
600     static const char *archivename = "__LIBZIPARCHIVE__UnZipFile__.zip";
601     const int N = 3;
602     char buf[MAX_BUFFER_SIZE];
603     char archive_filename[MAX_DIR_SIZE];
604     char filename[MAX_DIR_SIZE];
605     int i = 0;
606     int ret = 0;
607 
608     GenerateZipfile(data, archivename, N, buf, archive_filename, i, ret, pf_data);
609 
610     UnzipFileCheckDirectory(archivename, filename);
611 
612     UnzipFileCheckTxt(archivename, filename, data, N, buf, ret);
613 
614     UnzipFileCheckInDirectory(archivename, filename, data, N, buf, ret);
615 
616     sprintf_s(filename, MAX_DIR_SIZE, "classes.abc");
617     UnzipFileCheckPandaFile(archivename, filename, pf_data, ret);
618 
619     remove(archivename);
620     GTEST_COUT << "Success.\n";
621 }
622 
HWTEST(LIBZIPARCHIVE, UnZipUncompressedFile, testing::ext::TestSize.Level0)623 HWTEST(LIBZIPARCHIVE, UnZipUncompressedFile, testing::ext::TestSize.Level0)
624 {
625     static const char *data =
626         "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras feugiat et odio ac sollicitudin. Maecenas "
627         "lobortis ultrices eros sed pharetra. Phasellus in tortor rhoncus, aliquam augue ac, gravida elit. Sed "
628         "molestie dolor a vulputate tincidunt. Proin a tellus quam. Suspendisse id feugiat elit, non ornare lacus. "
629         "Mauris arcu ex, pretium quis dolor ut, porta iaculis eros. Vestibulum sagittis placerat diam, vitae efficitur "
630         "turpis ultrices sit amet. Etiam elementum bibendum congue. In sit amet dolor ultricies, suscipit arcu ac, "
631         "molestie urna. Mauris ultrices volutpat massa quis ultrices. Suspendisse rutrum lectus sit amet metus "
632         "laoreet, non porta sapien venenatis. Fusce ut massa et purus elementum lacinia. Sed tempus bibendum pretium.";
633 
634     /*
635      * creating an empty pandafile
636      */
637     std::vector<uint8_t> pf_data {};
638     {
639         pandasm::Parser p;
640 
641         auto source = R"()";
642 
643         std::string src_filename = "src.pa";
644         auto res = p.Parse(source, src_filename);
645         ASSERT_EQ(p.ShowError().err, pandasm::Error::ErrorType::ERR_NONE);
646 
647         auto pf = pandasm::AsmEmitter::Emit(res.Value());
648         ASSERT_NE(pf, nullptr);
649 
650         const auto header_ptr = reinterpret_cast<const uint8_t *>(pf->GetHeader());
651         pf_data.assign(header_ptr, header_ptr + sizeof(panda_file::File::Header));
652     }
653 
654     // The zip filename
655     static const char *archivename = "__LIBZIPARCHIVE__UnZipUncompressedFile__.zip";
656     const int N = 3;
657     char buf[MAX_BUFFER_SIZE];
658     char archive_filename[MAX_DIR_SIZE];
659     char filename[MAX_DIR_SIZE];
660     int i = 0;
661     int ret = 0;
662 
663     GenerateZipfile(data, archivename, N, buf, archive_filename, i, ret, pf_data, Z_NO_COMPRESSION);
664 
665     UnzipFileCheckDirectory(archivename, filename, Z_NO_COMPRESSION);
666 
667     UnzipFileCheckTxt(archivename, filename, data, N, buf, ret, Z_NO_COMPRESSION);
668 
669     UnzipFileCheckInDirectory(archivename, filename, data, N, buf, ret, Z_NO_COMPRESSION);
670 
671     (void)sprintf_s(filename, MAX_DIR_SIZE, "classes.abc");
672     UnzipFileCheckPandaFile(archivename, filename, pf_data, ret, Z_NO_COMPRESSION);
673 
674     remove(archivename);
675     GTEST_COUT << "Success.\n";
676 }
677 
HWTEST(LIBZIPARCHIVE, UnZipUncompressedPandaFile, testing::ext::TestSize.Level0)678 HWTEST(LIBZIPARCHIVE, UnZipUncompressedPandaFile, testing::ext::TestSize.Level0)
679 {
680     /*
681      * creating an empty pandafile
682      */
683     std::vector<uint8_t> pf_data {};
684     {
685         pandasm::Parser p;
686 
687         auto source = R"()";
688 
689         std::string src_filename = "src.pa";
690         auto res = p.Parse(source, src_filename);
691         ASSERT_EQ(p.ShowError().err, pandasm::Error::ErrorType::ERR_NONE);
692 
693         auto pf = pandasm::AsmEmitter::Emit(res.Value());
694         ASSERT_NE(pf, nullptr);
695 
696         const auto header_ptr = reinterpret_cast<const uint8_t *>(pf->GetHeader());
697         pf_data.assign(header_ptr, header_ptr + sizeof(panda_file::File::Header));
698     }
699 
700     // The zip filename
701     static const char *archivename = "__LIBZIPARCHIVE__UnZipUncompressedPandaFile__.zip";
702     char filename[MAX_DIR_SIZE];
703     int ret = 0;
704 
705     // Delete the test archive, so it doesn't keep growing as we run this test
706     remove(archivename);
707 
708     // Add pandafile into zip for testing
709     ret = CreateOrAddFileIntoZip(archivename, "class.abc", pf_data.data(), pf_data.size(), APPEND_STATUS_CREATE,
710                                  Z_NO_COMPRESSION);
711     if (ret != 0) {
712         ASSERT_EQ(1, 0) << "CreateOrAddFileIntoZip failed!";
713         return;
714     }
715     ret = CreateOrAddFileIntoZip(archivename, "classes.abc", pf_data.data(), pf_data.size(), APPEND_STATUS_ADDINZIP,
716                                  Z_NO_COMPRESSION);
717     if (ret != 0) {
718         ASSERT_EQ(1, 0) << "CreateOrAddFileIntoZip failed!";
719         return;
720     }
721 
722     sprintf_s(filename, MAX_DIR_SIZE, "class.abc");
723     UnzipFileCheckPandaFile(archivename, filename, pf_data, ret, Z_NO_COMPRESSION);
724     sprintf_s(filename, MAX_DIR_SIZE, "classes.abc");
725     UnzipFileCheckPandaFile(archivename, filename, pf_data, ret, Z_NO_COMPRESSION);
726 
727     remove(archivename);
728     GTEST_COUT << "Success.\n";
729 }
730 
HWTEST(LIBZIPARCHIVE, IllegalPathTest, testing::ext::TestSize.Level0)731 HWTEST(LIBZIPARCHIVE, IllegalPathTest, testing::ext::TestSize.Level0)
732 {
733     static const char *archivename = "__LIBZIPARCHIVE__ILLEGALPATHTEST__.zip";
734     int ret = CreateOrAddFileIntoZip(archivename, "illegal_path.abc", nullptr, 0, APPEND_STATUS_ADDINZIP,
735                                      Z_NO_COMPRESSION);
736     ASSERT_EQ(ret, ZIPARCHIVE_ERR);
737     ZipArchiveHandle zipfile = nullptr;
738     ASSERT_EQ(OpenArchive(zipfile, archivename), ZIPARCHIVE_ERR);
739     GlobalStat gi = GlobalStat();
740     ASSERT_EQ(GetGlobalFileInfo(zipfile, &gi), ZIPARCHIVE_ERR);
741     ASSERT_EQ(GoToNextFile(zipfile), ZIPARCHIVE_ERR);
742     ASSERT_EQ(LocateFile(zipfile, "illegal_path.abc"), ZIPARCHIVE_ERR);
743     EntryFileStat entry = EntryFileStat();
744     ASSERT_EQ(GetCurrentFileInfo(zipfile, &entry), ZIPARCHIVE_ERR);
745     ASSERT_EQ(CloseArchive(zipfile), ZIPARCHIVE_ERR);
746 
747     ASSERT_EQ(OpenArchiveFile(zipfile, nullptr), ZIPARCHIVE_ERR);
748     ASSERT_EQ(OpenCurrentFile(zipfile), ZIPARCHIVE_ERR);
749     ASSERT_EQ(CloseCurrentFile(zipfile), ZIPARCHIVE_ERR);
750     ASSERT_EQ(CloseArchiveFile(zipfile), ZIPARCHIVE_ERR);
751 }
752 }  // namespace panda::test
753