• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 }