1/*
2 * Copyright (c) 2023 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 "updatermain_fuzzer.h"
17
18#include <array>
19#include <cstddef>
20#include <cstdint>
21#include <iostream>
22#include <string>
23#include <vector>
24#include <sys/stat.h>
25#include <sys/types.h>
26#include "log/log.h"
27#include "updater_main.h"
28#include "misc_info/misc_info.h"
29#include "updater/updater_const.h"
30#include "securec.h"
31#include "utils.h"
32#include "updater/updater.h"
33#include "updater_ui_stub.h"
34
35using namespace Updater;
36using namespace std;
37constexpr uint32_t MAX_ARG_SIZE = 10;
38
39static void ParseParamsFuzzTest()
40{
41    UpdateMessage boot {};
42    const std::string commandFile = "/data/updater/command";
43    auto fp = std::unique_ptr<FILE, decltype(&fclose)>(fopen(commandFile.c_str(), "wb"), fclose);
44    if (fp == nullptr) {
45        return;
46    }
47    const std::string commandMsg = "boot_updater";
48    if (strncpy_s(boot.command, sizeof(boot.command) - 1, commandMsg.c_str(), commandMsg.size()) != 0) {
49        return;
50    }
51    if (strncpy_s(boot.update, sizeof(boot.update), "", sizeof(boot.update)) != 0) {
52        return;
53    }
54    WriteUpdaterMessage(commandFile, boot);
55    char **argv = new char *[1];
56    argv[0] = new char[MAX_ARG_SIZE];
57    if (strncpy_s(argv[0], MAX_ARG_SIZE, "./main", MAX_ARG_SIZE) != 0) {
58        return;
59    }
60    int argc = 1;
61    Utils::ParseParams(argc, argv);
62    PostUpdater(true);
63    delete argv[0];
64    delete []argv;
65}
66
67static void MianUpdaterFuzzTest()
68{
69    int argsSize = 24;
70    UpdateMessage boot {};
71    if (access("/data/updater/", 0)) {
72        int ret = mkdir("/data/updater/", S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH);
73        if (ret != 0) {
74            return;
75        }
76    }
77    const std::string commandFile = "/data/updater/command";
78    auto fp = std::unique_ptr<FILE, decltype(&fclose)>(fopen(commandFile.c_str(), "wb"), fclose);
79    if (fp == nullptr) {
80        return;
81    }
82
83    const std::string commandMsg = "boot_updater";
84    const std::string updateMsg = "--update_package=/data/updater/updater/updater_full.zip";
85    if (strncpy_s(boot.command, sizeof(boot.command) - 1, commandMsg.c_str(), commandMsg.size()) != 0) {
86        return;
87    }
88    if (strncpy_s(boot.update, sizeof(boot.update) - 1, updateMsg.c_str(), updateMsg.size()) != 0) {
89        return;
90    }
91    bool bRet = WriteUpdaterMessage(commandFile, boot);
92    if (!bRet) {
93        return;
94    }
95    char **argv = new char* [1];
96    argv[0] = new char[argsSize];
97    if (strncpy_s(argv[0], argsSize, "./UpdaterMain", argsSize) != 0) {
98        return;
99    }
100    int argc = 1;
101
102    int ret = UpdaterMain(argc, argv);
103    if (!ret) {
104        return;
105    }
106    delete argv[0];
107    delete []argv;
108}
109
110static void SdCardUpdateFuzzTest()
111{
112    int argsSize = 24;
113    UpdateMessage boot {};
114    if (access("/data/updater/", 0)) {
115        int ret = mkdir("/data/updater/", S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH);
116        if (ret != 0) {
117            return;
118        }
119    }
120    const std::string commandFile = "/data/updater/command";
121    auto fp = std::unique_ptr<FILE, decltype(&fclose)>(fopen(commandFile.c_str(), "wb"), fclose);
122    if (fp == nullptr) {
123        return;
124    }
125    const std::string commandMsg = "boot_updater";
126    const std::string updateMsg = "--sdcard_update";
127    if (strncpy_s(boot.command, sizeof(boot.command) - 1, commandMsg.c_str(), commandMsg.size()) != 0) {
128        return;
129    }
130    if (strncpy_s(boot.update, sizeof(boot.update) - 1, updateMsg.c_str(), updateMsg.size()) != 0) {
131        return;
132    }
133    bool bRet = WriteUpdaterMessage(commandFile, boot);
134    if (!bRet) {
135        return;
136    }
137    char **argv = new char* [1];
138    argv[0] = new char[argsSize];
139    if (strncpy_s(argv[0], argsSize, "./UpdaterMain", argsSize) != 0) {
140        return;
141    }
142    int argc = 1;
143    if (UpdaterMain(argc, argv) != 0) {
144        return;
145    }
146    delete argv[0];
147    delete []argv;
148}
149
150static void InstallUpdaterPackageFuzzTest()
151{
152    UpdaterParams upParams;
153    upParams.retryCount = 0;
154    upParams.callbackProgress = [] (float value) { UPDATER_UI_INSTANCE.ShowProgress(value); };
155    upParams.updatePackage.push_back("/data/updater/updater/updater_full.zip");
156    Hpackage::PkgManager::PkgManagerPtr pkgManager = Hpackage::PkgManager::CreatePackageInstance();
157    if (InstallUpdaterPackage(upParams, pkgManager) != UPDATE_ERROR) {
158        return;
159    }
160}
161
162static void DoUpdatePackagesFuzzTest()
163{
164    UpdaterParams upParams;
165    if (DoUpdatePackages(upParams) != UPDATE_CORRUPT) {
166        return;
167    }
168    upParams.updatePackage.push_back("/data/updater/updater/updater_full.zip");
169    if (DoUpdatePackages(upParams) != UPDATE_CORRUPT) {
170        return;
171    }
172}
173
174static void StartUpdaterEntryFuzzTest()
175{
176    UpdaterParams upParams;
177    upParams.factoryResetMode = "factory_wipe_data";
178    if (DoUpdatePackages(upParams) != UPDATE_CORRUPT) {
179        return;
180    }
181    upParams.factoryResetMode = "user_wipe_data";
182    if (DoUpdatePackages(upParams) != UPDATE_CORRUPT) {
183        return;
184    }
185    upParams.factoryResetMode = "menu_wipe_data";
186    if (DoUpdatePackages(upParams) != UPDATE_CORRUPT) {
187        return;
188    }
189    upParams.factoryResetMode = "";
190    if (DoUpdatePackages(upParams) != UPDATE_CORRUPT) {
191        return;
192    }
193}
194
195static void ExtractUpdaterBinaryFuzzTest()
196{
197    Hpackage::PkgManager::PkgManagerPtr pkgManager = Hpackage::PkgManager::CreatePackageInstance();
198    std::string path = "xxx";
199    int32_t ret = ExtractUpdaterBinary(pkgManager, path, UPDATER_BINARY);
200    if (ret != 1) {
201        return;
202    }
203    path = "/data/updater/updater/updater_full.zip";
204    ret = ExtractUpdaterBinary(pkgManager, path, UPDATER_BINARY);
205    Hpackage::PkgManager::ReleasePackageInstance(pkgManager);
206    if (ret != 1) {
207        return;
208    }
209}
210
211static void IsSpaceCapacitySufficientFuzzTest()
212{
213    UpdaterParams upParams {};
214    UpdaterStatus status = IsSpaceCapacitySufficient(upParams);
215    if (status != UPDATE_ERROR) {
216        return;
217    }
218    if (CheckStatvfs(0) != 0) {
219        return;
220    }
221    if (IsBatteryCapacitySufficient()) {
222        return;
223    }
224    upParams.updatePackage.push_back("/data/updater/updater/updater_full.zip");
225    status = IsSpaceCapacitySufficient(upParams);
226    if (status != UPDATE_SUCCESS) {
227        return;
228    }
229}
230
231static void ProgressFuzzTest()
232{
233    int progress = 0;
234    SetTmpProgressValue(progress);
235    if (GetTmpProgressValue() != 0) {
236        return;
237    }
238    ProgressSmoothHandler(0, 1);
239}
240
241static void UtilsFuzzTest(const uint8_t* data, size_t size)
242{
243    if (!Utils::IsDirExist(std::string(reinterpret_cast<const char*>(data), size))) {
244        return;
245    }
246    std::vector<std::string> files {};
247    if (Utils::GetFilesFromDirectory(std::string(reinterpret_cast<const char*>(data), size), files, false) < 0) {
248        return;
249    }
250    std::string filePath = std::string(reinterpret_cast<const char*>(data), size) + "MountForPath_fuzzer.fstable";
251    if (!Utils::IsFileExist(filePath)) {
252        return;
253    }
254}
255
256namespace OHOS {
257    void FuzzUpdater(const uint8_t* data, size_t size)
258    {
259        ParseParamsFuzzTest();
260        MianUpdaterFuzzTest();
261        SdCardUpdateFuzzTest();
262        InstallUpdaterPackageFuzzTest();
263        DoUpdatePackagesFuzzTest();
264        StartUpdaterEntryFuzzTest();
265        ExtractUpdaterBinaryFuzzTest();
266        IsSpaceCapacitySufficientFuzzTest();
267        ProgressFuzzTest();
268        UtilsFuzzTest(data, size);
269    }
270}
271
272/* Fuzzer entry point */
273extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size)
274{
275    /* Run your code on data */
276    OHOS::FuzzUpdater(data, size);
277    return 0;
278}
279
280