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,size_t size)76 void GoToNextFileFuzzTest(const uint8_t* data, [[maybe_unused]] size_t size)
77 {
78 {
79 // handle is not nullptr
80 // creating an empty pandafile
81 const char* s = reinterpret_cast<char*>(const_cast<uint8_t*>(data));
82 std::vector<uint8_t> pf_data {};
83 int err = MakePfData(pf_data);
84 if (err != 0) {
85 return;
86 }
87 static const char* archive_name = "__LIBZIPARCHIVE__ZipFile__.zip";
88 const int n = 3;
89 char buf[MAX_BUFFER_SIZE];
90 char archive_filename[MAX_DIR_SIZE];
91 int i = 0;
92 int ret = 0;
93 GenerateZipfile(s, archive_name, n, buf, archive_filename, i, ret, pf_data);
94
95 // Quick Check
96 panda::ZipArchiveHandle zipfile = nullptr;
97 if (panda::OpenArchive(zipfile, archive_name) != 0) {
98 return;
99 }
100 panda::GlobalStat gi = panda::GlobalStat();
101 if (panda::GetGlobalFileInfo(zipfile, &gi) != 0) {
102 return;
103 }
104 int entrynum = static_cast<int>(gi.GetNumberOfEntry());
105 for (i = 0; i < entrynum; ++i) {
106 panda::EntryFileStat file_stat;
107 if (panda::GetCurrentFileInfo(zipfile, &file_stat) != 0) {
108 panda::CloseArchive(zipfile);
109 return;
110 }
111 if ((i + 1) < entrynum) {
112 if (panda::GoToNextFile(zipfile) != 0) {
113 panda::CloseArchive(zipfile);
114 return;
115 }
116 }
117 }
118 panda::CloseArchive(zipfile);
119 (void)remove(archive_name);
120 }
121 }
122 }
123
124 /* Fuzzer entry point */
LLVMFuzzerTestOneInput(const uint8_t * data,size_t size)125 extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size)
126 {
127 /* Run your code on data */
128 OHOS::GoToNextFileFuzzTest(data, size);
129 return 0;
130 }