1fb299fa2Sopenharmony_ci/*
2fb299fa2Sopenharmony_ci * Copyright (c) 2023 Huawei Device Co., Ltd.
3fb299fa2Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
4fb299fa2Sopenharmony_ci * you may not use this file except in compliance with the License.
5fb299fa2Sopenharmony_ci * You may obtain a copy of the License at
6fb299fa2Sopenharmony_ci *
7fb299fa2Sopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
8fb299fa2Sopenharmony_ci *
9fb299fa2Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
10fb299fa2Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
11fb299fa2Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12fb299fa2Sopenharmony_ci * See the License for the specific language governing permissions and
13fb299fa2Sopenharmony_ci * limitations under the License.
14fb299fa2Sopenharmony_ci */
15fb299fa2Sopenharmony_ci
16fb299fa2Sopenharmony_ci#include "scriptmanager_fuzzer.h"
17fb299fa2Sopenharmony_ci
18fb299fa2Sopenharmony_ci#include <fcntl.h>
19fb299fa2Sopenharmony_ci#include <iostream>
20fb299fa2Sopenharmony_ci#include <sys/mman.h>
21fb299fa2Sopenharmony_ci#include <unistd.h>
22fb299fa2Sopenharmony_ci#include <vector>
23fb299fa2Sopenharmony_ci#include "hash_data_verifier.h"
24fb299fa2Sopenharmony_ci#include "log.h"
25fb299fa2Sopenharmony_ci#include "pkg_stream.h"
26fb299fa2Sopenharmony_ci#include "pkg_utils.h"
27fb299fa2Sopenharmony_ci#include "scope_guard.h"
28fb299fa2Sopenharmony_ci#include "script_instructionhelper.h"
29fb299fa2Sopenharmony_ci#include "script_manager_impl.h"
30fb299fa2Sopenharmony_ci#include "script_manager.h"
31fb299fa2Sopenharmony_ci#include "script_unittest.h"
32fb299fa2Sopenharmony_ci#include "script_utils.h"
33fb299fa2Sopenharmony_ci#include "utils.h"
34fb299fa2Sopenharmony_ci
35fb299fa2Sopenharmony_ciusing namespace Hpackage;
36fb299fa2Sopenharmony_ciusing namespace Uscript;
37fb299fa2Sopenharmony_ciusing namespace Updater;
38fb299fa2Sopenharmony_ci
39fb299fa2Sopenharmony_cinamespace OHOS {
40fb299fa2Sopenharmony_ciconstexpr int32_t SCRIPT_TEST_PRIORITY_NUM = 3;
41fb299fa2Sopenharmony_ciconstexpr int32_t SCRIPT_TEST_LAST_PRIORITY = 2;
42fb299fa2Sopenharmony_ciconst std::string FUZZ_TEST_PATH_FROM = "/data/fuzz/test/";
43fb299fa2Sopenharmony_ci
44fb299fa2Sopenharmony_ciclass TestPkgManager : public TestScriptPkgManager {
45fb299fa2Sopenharmony_cipublic:
46fb299fa2Sopenharmony_ci    const FileInfo *GetFileInfo(const std::string &fileId) override
47fb299fa2Sopenharmony_ci    {
48fb299fa2Sopenharmony_ci        static FileInfo fileInfo {};
49fb299fa2Sopenharmony_ci        static std::vector<std::string> testFileNames = {
50fb299fa2Sopenharmony_ci            "loadScript.us",
51fb299fa2Sopenharmony_ci            "test_function.us",
52fb299fa2Sopenharmony_ci            "test_if.us",
53fb299fa2Sopenharmony_ci            "test_logic.us",
54fb299fa2Sopenharmony_ci            "testscript.us",
55fb299fa2Sopenharmony_ci            "test_math.us",
56fb299fa2Sopenharmony_ci            "test_native.us",
57fb299fa2Sopenharmony_ci            "Verse-script.us",
58fb299fa2Sopenharmony_ci            "test_script.us"
59fb299fa2Sopenharmony_ci        };
60fb299fa2Sopenharmony_ci        if (std::find(testFileNames.begin(), testFileNames.end(), fileId) != testFileNames.end()) {
61fb299fa2Sopenharmony_ci            return &fileInfo;
62fb299fa2Sopenharmony_ci        }
63fb299fa2Sopenharmony_ci        if (fileId == "hash_signed_data") {
64fb299fa2Sopenharmony_ci            fileInfo.unpackedSize = GetFileSize(FUZZ_TEST_PATH_FROM + fileId);
65fb299fa2Sopenharmony_ci            return &fileInfo;
66fb299fa2Sopenharmony_ci        }
67fb299fa2Sopenharmony_ci        return nullptr;
68fb299fa2Sopenharmony_ci    }
69fb299fa2Sopenharmony_ci    int32_t CreatePkgStream(StreamPtr &stream, const std::string &fileName, const PkgBuffer &buffer) override
70fb299fa2Sopenharmony_ci    {
71fb299fa2Sopenharmony_ci        PKG_LOGI("create pkg stream success for %s ", fileName.c_str());
72fb299fa2Sopenharmony_ci        stream = new MemoryMapStream(this, fileName, buffer, PkgStream::PkgStreamType_Buffer);
73fb299fa2Sopenharmony_ci        return PKG_SUCCESS;
74fb299fa2Sopenharmony_ci    }
75fb299fa2Sopenharmony_ci    int32_t ExtractFile(const std::string &fileId, StreamPtr output) override
76fb299fa2Sopenharmony_ci    {
77fb299fa2Sopenharmony_ci        if (fileId != "hash_signed_data") {
78fb299fa2Sopenharmony_ci            return PKG_SUCCESS;
79fb299fa2Sopenharmony_ci        }
80fb299fa2Sopenharmony_ci        if (output == nullptr) {
81fb299fa2Sopenharmony_ci            return PKG_INVALID_STREAM;
82fb299fa2Sopenharmony_ci        }
83fb299fa2Sopenharmony_ci        auto fd = open((FUZZ_TEST_PATH_FROM + fileId).c_str(), O_RDWR);
84fb299fa2Sopenharmony_ci        if (fd == -1) {
85fb299fa2Sopenharmony_ci            PKG_LOGE("file %s not existed", (FUZZ_TEST_PATH_FROM + fileId).c_str());
86fb299fa2Sopenharmony_ci            return PKG_INVALID_FILE;
87fb299fa2Sopenharmony_ci        }
88fb299fa2Sopenharmony_ci        ON_SCOPE_EXIT(close) {
89fb299fa2Sopenharmony_ci            close(fd);
90fb299fa2Sopenharmony_ci        };
91fb299fa2Sopenharmony_ci        std::string content {};
92fb299fa2Sopenharmony_ci        if (!Utils::ReadFileToString(fd, content)) {
93fb299fa2Sopenharmony_ci            PKG_LOGE("read file to string failed");
94fb299fa2Sopenharmony_ci            return PKG_INVALID_FILE;
95fb299fa2Sopenharmony_ci        }
96fb299fa2Sopenharmony_ci        auto stream = static_cast<MemoryMapStream *>(output);
97fb299fa2Sopenharmony_ci        PkgBuffer buffer = {};
98fb299fa2Sopenharmony_ci        stream->GetBuffer(buffer);
99fb299fa2Sopenharmony_ci        if (content.size() + 1 != buffer.length) {
100fb299fa2Sopenharmony_ci            PKG_LOGE("content size is not valid, %u != %u", content.size(), buffer.data.size());
101fb299fa2Sopenharmony_ci            return PKG_INVALID_FILE;
102fb299fa2Sopenharmony_ci        }
103fb299fa2Sopenharmony_ci        std::copy(content.begin(), content.end(), buffer.buffer);
104fb299fa2Sopenharmony_ci        return PKG_SUCCESS;
105fb299fa2Sopenharmony_ci    }
106fb299fa2Sopenharmony_ci    int32_t CreatePkgStream(StreamPtr &stream, const std::string &fileName,
107fb299fa2Sopenharmony_ci         size_t size, int32_t type) override
108fb299fa2Sopenharmony_ci    {
109fb299fa2Sopenharmony_ci        FILE *file = nullptr;
110fb299fa2Sopenharmony_ci        std::string realFileName = fileName;
111fb299fa2Sopenharmony_ci        auto pos = fileName.rfind('/');
112fb299fa2Sopenharmony_ci        if (pos != std::string::npos) {
113fb299fa2Sopenharmony_ci            realFileName = fileName.substr(pos + 1);
114fb299fa2Sopenharmony_ci        }
115fb299fa2Sopenharmony_ci        char realPath[PATH_MAX + 1] = {};
116fb299fa2Sopenharmony_ci        if (realpath((FUZZ_TEST_PATH_FROM + realFileName).c_str(), realPath) == nullptr) {
117fb299fa2Sopenharmony_ci            LOG(ERROR) << (FUZZ_TEST_PATH_FROM + realFileName) << " realpath failed";
118fb299fa2Sopenharmony_ci            return PKG_INVALID_FILE;
119fb299fa2Sopenharmony_ci        }
120fb299fa2Sopenharmony_ci        file = fopen(realPath, "rb");
121fb299fa2Sopenharmony_ci        if (file != nullptr) {
122fb299fa2Sopenharmony_ci            stream = new FileStream(this, realFileName, file, PkgStream::PkgStreamType_Read);
123fb299fa2Sopenharmony_ci            return USCRIPT_SUCCESS;
124fb299fa2Sopenharmony_ci        }
125fb299fa2Sopenharmony_ci        PKG_LOGE("Fail to open file %s ", realFileName.c_str());
126fb299fa2Sopenharmony_ci        return PKG_INVALID_FILE;
127fb299fa2Sopenharmony_ci    }
128fb299fa2Sopenharmony_ci    void ClosePkgStream(StreamPtr &stream) override
129fb299fa2Sopenharmony_ci    {
130fb299fa2Sopenharmony_ci        delete stream;
131fb299fa2Sopenharmony_ci    }
132fb299fa2Sopenharmony_ci};
133fb299fa2Sopenharmony_ci
134fb299fa2Sopenharmony_ciclass FuzzTestScriptInstructionSparseImageWrite : public Uscript::UScriptInstruction {
135fb299fa2Sopenharmony_cipublic:
136fb299fa2Sopenharmony_ci    FuzzTestScriptInstructionSparseImageWrite() {}
137fb299fa2Sopenharmony_ci    virtual ~FuzzTestScriptInstructionSparseImageWrite() {}
138fb299fa2Sopenharmony_ci    int32_t Execute(Uscript::UScriptEnv &env, Uscript::UScriptContext &context) override
139fb299fa2Sopenharmony_ci    {
140fb299fa2Sopenharmony_ci        std::string partitionName = {};
141fb299fa2Sopenharmony_ci        int32_t ret = context.GetParam(0, partitionName);
142fb299fa2Sopenharmony_ci        if (ret != USCRIPT_SUCCESS) {
143fb299fa2Sopenharmony_ci            LOG(ERROR) << "Error to get param";
144fb299fa2Sopenharmony_ci            return ret;
145fb299fa2Sopenharmony_ci        }
146fb299fa2Sopenharmony_ci        LOG(INFO) << "UScriptInstructionSparseImageWrite::Execute " << partitionName;
147fb299fa2Sopenharmony_ci        if (env.GetPkgManager() != nullptr) {
148fb299fa2Sopenharmony_ci            return ret;
149fb299fa2Sopenharmony_ci        }
150fb299fa2Sopenharmony_ci        LOG(ERROR) << "Error to get pkg manager";
151fb299fa2Sopenharmony_ci        return USCRIPT_ERROR_EXECUTE;
152fb299fa2Sopenharmony_ci    }
153fb299fa2Sopenharmony_ci};
154fb299fa2Sopenharmony_ci
155fb299fa2Sopenharmony_ciclass FuzzTestScriptInstructionFactory : public UScriptInstructionFactory {
156fb299fa2Sopenharmony_cipublic:
157fb299fa2Sopenharmony_ci    virtual int32_t CreateInstructionInstance(UScriptInstructionPtr& instr, const std::string& name)
158fb299fa2Sopenharmony_ci    {
159fb299fa2Sopenharmony_ci        if (name == "sparse_image_write") {
160fb299fa2Sopenharmony_ci            instr = new (std::nothrow) FuzzTestScriptInstructionSparseImageWrite();
161fb299fa2Sopenharmony_ci        }
162fb299fa2Sopenharmony_ci        return USCRIPT_SUCCESS;
163fb299fa2Sopenharmony_ci    }
164fb299fa2Sopenharmony_ci    virtual void DestoryInstructionInstance(UScriptInstructionPtr& instr)
165fb299fa2Sopenharmony_ci    {
166fb299fa2Sopenharmony_ci        delete instr;
167fb299fa2Sopenharmony_ci        instr = nullptr;
168fb299fa2Sopenharmony_ci    }
169fb299fa2Sopenharmony_ci    FuzzTestScriptInstructionFactory() {}
170fb299fa2Sopenharmony_ci    virtual ~FuzzTestScriptInstructionFactory() {}
171fb299fa2Sopenharmony_ci};
172fb299fa2Sopenharmony_ci
173fb299fa2Sopenharmony_ciclass FuzzTestScriptEnv : public UScriptEnv {
174fb299fa2Sopenharmony_cipublic:
175fb299fa2Sopenharmony_ci    explicit FuzzTestScriptEnv(Hpackage::PkgManager::PkgManagerPtr pkgManager) : UScriptEnv(pkgManager) {}
176fb299fa2Sopenharmony_ci    ~FuzzTestScriptEnv()
177fb299fa2Sopenharmony_ci    {
178fb299fa2Sopenharmony_ci        if (factory_ != nullptr) {
179fb299fa2Sopenharmony_ci            delete factory_;
180fb299fa2Sopenharmony_ci            factory_ = nullptr;
181fb299fa2Sopenharmony_ci        }
182fb299fa2Sopenharmony_ci    }
183fb299fa2Sopenharmony_ci
184fb299fa2Sopenharmony_ci    virtual UScriptInstructionFactoryPtr GetInstructionFactory()
185fb299fa2Sopenharmony_ci    {
186fb299fa2Sopenharmony_ci        if (factory_ == nullptr) {
187fb299fa2Sopenharmony_ci            factory_ = new FuzzTestScriptInstructionFactory();
188fb299fa2Sopenharmony_ci        }
189fb299fa2Sopenharmony_ci        return factory_;
190fb299fa2Sopenharmony_ci    }
191fb299fa2Sopenharmony_ci
192fb299fa2Sopenharmony_ci    virtual void PostMessage(const std::string &cmd, std::string content) {}
193fb299fa2Sopenharmony_ci
194fb299fa2Sopenharmony_ci    virtual const std::vector<std::string> GetInstructionNames() const
195fb299fa2Sopenharmony_ci    {
196fb299fa2Sopenharmony_ci        return {"sparse_image_write"};
197fb299fa2Sopenharmony_ci    }
198fb299fa2Sopenharmony_ci
199fb299fa2Sopenharmony_ci    virtual bool IsRetry() const
200fb299fa2Sopenharmony_ci    {
201fb299fa2Sopenharmony_ci        return isRetry;
202fb299fa2Sopenharmony_ci    }
203fb299fa2Sopenharmony_ci
204fb299fa2Sopenharmony_ci    virtual PostMessageFunction GetPostmsgFunc()
205fb299fa2Sopenharmony_ci    {
206fb299fa2Sopenharmony_ci        return nullptr;
207fb299fa2Sopenharmony_ci    }
208fb299fa2Sopenharmony_ci    UScriptInstructionFactory *factory_ = nullptr;
209fb299fa2Sopenharmony_ciprivate:
210fb299fa2Sopenharmony_ci    bool isRetry = false;
211fb299fa2Sopenharmony_ci};
212fb299fa2Sopenharmony_ci
213fb299fa2Sopenharmony_ciclass FuzzScriptTest {
214fb299fa2Sopenharmony_cipublic:
215fb299fa2Sopenharmony_ci    FuzzScriptTest()
216fb299fa2Sopenharmony_ci    {
217fb299fa2Sopenharmony_ci        InitUpdaterLogger("UPDATER", "updater_log.log", "updater_status.log", "error_code.log");
218fb299fa2Sopenharmony_ci    }
219fb299fa2Sopenharmony_ci
220fb299fa2Sopenharmony_ci    ~FuzzScriptTest()
221fb299fa2Sopenharmony_ci    {
222fb299fa2Sopenharmony_ci        ScriptManager::ReleaseScriptManager();
223fb299fa2Sopenharmony_ci    }
224fb299fa2Sopenharmony_ci
225fb299fa2Sopenharmony_ci    int TestUscriptExecute(std::string &path)
226fb299fa2Sopenharmony_ci    {
227fb299fa2Sopenharmony_ci        int32_t ret {};
228fb299fa2Sopenharmony_ci        TestPkgManager packageManager;
229fb299fa2Sopenharmony_ci        auto env = std::make_unique<FuzzTestScriptEnv>(&packageManager);
230fb299fa2Sopenharmony_ci        HashDataVerifier verifier {&packageManager};
231fb299fa2Sopenharmony_ci        verifier.LoadHashDataAndPkcs7(path);
232fb299fa2Sopenharmony_ci        ScriptManager *manager = ScriptManager::GetScriptManager(env.get(), &verifier);
233fb299fa2Sopenharmony_ci        if (manager == nullptr) {
234fb299fa2Sopenharmony_ci            USCRIPT_LOGI("create manager fail ret:%d", ret);
235fb299fa2Sopenharmony_ci            return USCRIPT_INVALID_SCRIPT;
236fb299fa2Sopenharmony_ci        }
237fb299fa2Sopenharmony_ci        for (auto priority : {SCRIPT_TEST_PRIORITY_NUM, 0, 1, SCRIPT_TEST_LAST_PRIORITY}) {
238fb299fa2Sopenharmony_ci            ret = manager->ExecuteScript(priority);
239fb299fa2Sopenharmony_ci            USCRIPT_LOGI("ExecuteScript ret:%d", ret);
240fb299fa2Sopenharmony_ci        }
241fb299fa2Sopenharmony_ci        ScriptManager::ReleaseScriptManager();
242fb299fa2Sopenharmony_ci        return ret;
243fb299fa2Sopenharmony_ci    }
244fb299fa2Sopenharmony_ci
245fb299fa2Sopenharmony_ciprotected:
246fb299fa2Sopenharmony_ci    void SetUp() {}
247fb299fa2Sopenharmony_ci    void TearDown() {}
248fb299fa2Sopenharmony_ci    void TestBody() {}
249fb299fa2Sopenharmony_ci
250fb299fa2Sopenharmony_ciprivate:
251fb299fa2Sopenharmony_ci    std::vector<std::string> testFileNames_ = {
252fb299fa2Sopenharmony_ci        "loadScript.us",
253fb299fa2Sopenharmony_ci        "registerCmd.us",
254fb299fa2Sopenharmony_ci        "test_function.us",
255fb299fa2Sopenharmony_ci        "test_math.us",
256fb299fa2Sopenharmony_ci        "test_logic.us",
257fb299fa2Sopenharmony_ci        "test_native.us",
258fb299fa2Sopenharmony_ci        "test_script.us"
259fb299fa2Sopenharmony_ci        "test_if.us",
260fb299fa2Sopenharmony_ci        "testscript.us",
261fb299fa2Sopenharmony_ci        "Verse-script.us",
262fb299fa2Sopenharmony_ci    };
263fb299fa2Sopenharmony_ci};
264fb299fa2Sopenharmony_ci
265fb299fa2Sopenharmony_civoid FuzzScriptManager(const uint8_t *data, size_t size)
266fb299fa2Sopenharmony_ci{
267fb299fa2Sopenharmony_ci    FuzzScriptTest test;
268fb299fa2Sopenharmony_ci    std::string path = std::string(reinterpret_cast<const char*>(data), size);
269fb299fa2Sopenharmony_ci    test.TestUscriptExecute(path);
270fb299fa2Sopenharmony_ci}
271fb299fa2Sopenharmony_ci}
272fb299fa2Sopenharmony_ci
273fb299fa2Sopenharmony_ci/* Fuzzer entry point */
274fb299fa2Sopenharmony_ciextern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size)
275fb299fa2Sopenharmony_ci{
276fb299fa2Sopenharmony_ci    /* Run your code on data */
277fb299fa2Sopenharmony_ci    OHOS::FuzzScriptManager(data, size);
278fb299fa2Sopenharmony_ci    return 0;
279fb299fa2Sopenharmony_ci}
280fb299fa2Sopenharmony_ci
281