1 /*
2 * Copyright (c) 2024 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 "gotonextfile_fuzzer.h"
17
18 #include <cstdio>
19
20 #include "assembler/assembly-emitter.h"
21 #include "assembler/assembly-parser.h"
22 #include "libziparchive/zip_archive.h"
23 #include "libpandafile/file.h"
24
25 constexpr size_t MAX_BUFFER_SIZE = 2048;
26 constexpr size_t MAX_DIR_SIZE = 64;
27
28 namespace OHOS {
GenerateZipfile(const char* data, const char* archive_name, int n, char* buf, char* archive_filename, int& i, int& ret, std::vector<uint8_t>& pf_data, int level = Z_BEST_COMPRESSION)29 void GenerateZipfile(const char* data, const char* archive_name, int n, char* buf, char* archive_filename, int& i,
30 int& ret, std::vector<uint8_t>& pf_data, int level = Z_BEST_COMPRESSION)
31 {
32 // Delete the test archive, so it doesn't keep growing as we run this test
33 (void)remove(archive_name);
34 // Create and append a directory entry for testing
35 ret = panda::CreateOrAddFileIntoZip(archive_name, "directory/", NULL, 0, APPEND_STATUS_CREATE, level);
36 if (ret != 0) {
37 return;
38 }
39 int err = 0;
40 // Append a bunch of text files to the test archive
41 for (i = (n - 1); i >= 0; --i) {
42 err = sprintf_s(archive_filename, MAX_DIR_SIZE, "%d.txt", i);
43 if (err != 0) {
44 return;
45 }
46 err = sprintf_s(buf, MAX_BUFFER_SIZE, "%d %s %d", (n - 1) - i, data, i);
47 if (err != 0) {
48 return;
49 }
50 ret = panda::CreateOrAddFileIntoZip(archive_name, archive_filename, buf, strlen(buf) + 1,
51 APPEND_STATUS_ADDINZIP, level);
52 if (ret != 0) {
53 return;
54 }
55 }
56 }
57
MakePfData(std::vector<uint8_t>& pf_data)58 int MakePfData(std::vector<uint8_t>& pf_data)
59 {
60 panda::pandasm::Parser p;
61 auto source = R"()";
62 std::string src_filename = "src.pa";
63 auto res = p.Parse(source, src_filename);
64 if (p.ShowError().err != panda::pandasm::Error::ErrorType::ERR_NONE) {
65 return 1;
66 }
67 auto pf = panda::pandasm::AsmEmitter::Emit(res.Value());
68 if (pf == nullptr) {
69 return 1;
70 }
71 const auto header_ptr = reinterpret_cast<const uint8_t *>(pf->GetHeader());
72 pf_data.assign(header_ptr, header_ptr + sizeof(panda::panda_file::File::Header));
73 return 0;
74 }
75
GoToNextFileFuzzTest(const uint8_t* data, [[maybe_unused]] size_t size)76 void GoToNextFileFuzzTest(const uint8_t* data, [[maybe_unused]] size_t size)
77 {
78 {
79 // handle is nullptr
80 panda::ZipArchiveHandle handle = nullptr;
81 panda::GoToNextFile(handle);
82 }
83
84 {
85 // handle is not nullptr
86 // creating an empty pandafile
87 const char* s = reinterpret_cast<char*>(const_cast<uint8_t*>(data));
88 std::vector<uint8_t> pf_data {};
89 int err = MakePfData(pf_data);
90 if (err != 0) {
91 return;
92 }
93 static const char* archive_name = "__LIBZIPARCHIVE__ZipFile__.zip";
94 const int n = 3;
95 char buf[MAX_BUFFER_SIZE];
96 char archive_filename[MAX_DIR_SIZE];
97 int i = 0;
98 int ret = 0;
99 GenerateZipfile(s, archive_name, n, buf, archive_filename, i, ret, pf_data);
100
101 // Quick Check
102 panda::ZipArchiveHandle zipfile = nullptr;
103 if (panda::OpenArchive(zipfile, archive_name) != 0) {
104 return;
105 }
106 panda::GlobalStat gi = panda::GlobalStat();
107 if (panda::GetGlobalFileInfo(zipfile, &gi) != 0) {
108 return;
109 }
110 int entrynum = static_cast<int>(gi.GetNumberOfEntry());
111 for (i = 0; i < entrynum; ++i) {
112 panda::EntryFileStat file_stat;
113 if (panda::GetCurrentFileInfo(zipfile, &file_stat) != 0) {
114 panda::CloseArchive(zipfile);
115 return;
116 }
117 if ((i + 1) < entrynum) {
118 if (panda::GoToNextFile(zipfile) != 0) {
119 panda::CloseArchive(zipfile);
120 return;
121 }
122 }
123 }
124 panda::CloseArchive(zipfile);
125 (void)remove(archive_name);
126 }
127 }
128 }
129
130 /* Fuzzer entry point */
LLVMFuzzerTestOneInput(const uint8_t* data, size_t size)131 extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size)
132 {
133 /* Run your code on data */
134 OHOS::GoToNextFileFuzzTest(data, size);
135 return 0;
136 }