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 "napicommonwant_fuzzer.h"
17
18#include <cstddef>
19#include <cstdint>
20
21#define private public
22#define protected public
23#include "napi_common_want.h"
24#undef protected
25#undef private
26
27#include "ability_record.h"
28#include "array_wrapper.h"
29#include "bool_wrapper.h"
30#include "byte_wrapper.h"
31#include "double_wrapper.h"
32#include "float_wrapper.h"
33#include "int_wrapper.h"
34#include "long_wrapper.h"
35#include "short_wrapper.h"
36#include "string_wrapper.h"
37#include "zchar_wrapper.h"
38#include "remote_object_wrapper.h"
39#include "js_runtime_lite.h"
40#include "js_environment.h"
41
42using namespace OHOS::AAFwk;
43using namespace OHOS::AppExecFwk;
44using namespace OHOS::AbilityRuntime;
45
46namespace OHOS {
47namespace {
48constexpr int INPUT_ZERO = 0;
49constexpr int INPUT_ONE = 1;
50constexpr int INPUT_THREE = 3;
51constexpr size_t FOO_MAX_LEN = 1024;
52constexpr size_t U32_AT_SIZE = 4;
53constexpr uint8_t ENABLE = 2;
54constexpr size_t OFFSET_ZERO = 24;
55constexpr size_t OFFSET_ONE = 16;
56constexpr size_t OFFSET_TWO = 8;
57}
58
59uint32_t GetU32Data(const char* ptr)
60{
61    // convert fuzz input data to an integer
62    return (ptr[INPUT_ZERO] << OFFSET_ZERO) | (ptr[INPUT_ONE] << OFFSET_ONE) | (ptr[ENABLE] << OFFSET_TWO) |
63        ptr[INPUT_THREE];
64}
65
66sptr<Token> GetFuzzAbilityToken()
67{
68    sptr<Token> token = nullptr;
69    AbilityRequest abilityRequest;
70    abilityRequest.appInfo.bundleName = "com.example.fuzzTest";
71    abilityRequest.abilityInfo.name = "MainAbility";
72    abilityRequest.abilityInfo.type = AbilityType::DATA;
73    std::shared_ptr<AbilityRecord> abilityRecord = AbilityRecord::CreateAbilityRecord(abilityRequest);
74    if (abilityRecord) {
75        token = abilityRecord->GetToken();
76    }
77    return token;
78}
79
80void NapiCommonWantFuzztest1(bool boolParam, std::string &stringParam, int32_t int32Param)
81{
82    napi_env env = nullptr;
83    ElementName elementName;
84    elementName.SetDeviceID(stringParam);
85    elementName.SetBundleName(stringParam);
86    elementName.SetAbilityName(stringParam);
87    elementName.SetModuleName(stringParam);
88    WrapElementName(env, elementName); // branch failed
89    napi_value param = nullptr;
90    UnwrapElementName(env, param, elementName); // branch failed
91    AAFwk::WantParams wantParams1;
92    WrapWantParams(env, wantParams1); // branch failed
93    wantParams1.SetParam("intf1", String::Box(stringParam));
94    wantParams1.SetParam("intf2", Long::Box(int32Param));
95    wantParams1.SetParam("intf3", Boolean::Box(boolParam));
96    wantParams1.SetParam("intf4", Integer::Box(int32Param));
97    wantParams1.SetParam("intf5", Float::Box(int32Param));
98    wantParams1.SetParam("intf5", RemoteObjectWrap::Box(nullptr));
99    wantParams1.SetParam("intf6", Char::Box(int32Param));
100    wantParams1.SetParam("intf7", Double::Box(int32Param));
101    wantParams1.SetParam("intf8", Byte::Box(int32Param));
102    std::size_t size = 3; // 3 means arraysize.
103    sptr<IArray> ao = new (std::nothrow) Array(size, g_IID_IBoolean);
104    if (ao != nullptr) {
105        for (std::size_t i = 0; i < size; i++) {
106            ao->Set(i, Boolean::Box(boolParam));
107        }
108        wantParams1.SetParam("intf8", ao);
109    }
110    WrapWantParams(env, wantParams1); // branch failed
111    UnwrapWantParams(env, param, wantParams1); // branch failed
112    BlackListFilter(Want::PARAM_RESV_WINDOW_MODE); // branch
113    BlackListFilter(Want::PARAM_RESV_DISPLAY_ID); // branch
114    BlackListFilter(stringParam); // branch
115    Want want;
116    WrapWant(env, want); // branch
117    UnwrapWant(env, param, want); // branch
118    int resultCode = 0;
119    WrapAbilityResult(env, resultCode, want); // branch
120    UnWrapAbilityResult(env, param, resultCode, want); // branch
121    napi_value jsProValue = nullptr;
122    HandleNapiObject(env, param, jsProValue, stringParam, wantParams1); // branch
123    IsSpecialObject(env, param, stringParam, stringParam, static_cast<napi_valuetype>(int32Param)); // branch
124    HandleFdObject(env, param, stringParam, wantParams1); // branch
125    HandleRemoteObject(env, param, stringParam, wantParams1); // branch
126    CreateJsWant(env, want); // branch
127    CreateJsWantParams(env, wantParams1); // branch
128}
129
130void NapiCommonWantFuzztest2(bool boolParam, std::string &stringParam, int32_t int32Param)
131{
132    napi_env env = nullptr;
133    AAFwk::WantParams wantParams1;
134    napi_value object = nullptr;
135    InnerWrapJsWantParamsWantParams(env, object, stringParam, wantParams1); // failed
136    std::size_t size = 3; // 3 means arraysize.
137    sptr<IArray> ao = new (std::nothrow) Array(size, g_IID_IBoolean);
138    if (ao != nullptr) {
139        for (std::size_t i = 0; i < size; i++) {
140            ao->Set(i, Boolean::Box(boolParam));
141        }
142    }
143    WrapJsWantParamsArray(env, object, stringParam, ao); // branch
144}
145
146void NapiCommonWantFuzztest3(bool boolParam, std::string &stringParam, int32_t int32Param)
147{
148    std::shared_ptr<OHOS::JsEnv::JsEnvironment> jsEnv = nullptr;
149    AbilityRuntime::JsRuntime::Options options;
150    auto err = JsRuntimeLite::GetInstance().CreateJsEnv(options, jsEnv);
151    napi_env env = reinterpret_cast<napi_env>(jsEnv->GetNativeEngine());
152    ElementName elementName1;
153    elementName1.SetDeviceID(stringParam);
154    elementName1.SetBundleName(stringParam);
155    elementName1.SetAbilityName(stringParam);
156    elementName1.SetModuleName(stringParam);
157    napi_value jsObject = WrapElementName(env, elementName1); // branch
158
159    napi_value param = nullptr;
160    ElementName elementName2;
161    UnwrapElementName(env, param, elementName2); // branch null param
162    ElementName elementName3;
163    UnwrapElementName(env, jsObject, elementName3); //  branch not null param
164
165    AAFwk::WantParams wantParams1;
166    WrapWantParams(env, wantParams1);
167    wantParams1.SetParam("intf1", String::Box(stringParam));
168    wantParams1.SetParam("intf2", Long::Box(int32Param));
169    wantParams1.SetParam("intf3", Boolean::Box(boolParam));
170    wantParams1.SetParam("intf4", Integer::Box(int32Param));
171    wantParams1.SetParam("intf5", Float::Box(int32Param));
172    wantParams1.SetParam("intf5", RemoteObjectWrap::Box(nullptr));
173    wantParams1.SetParam("intf6", Char::Box(int32Param));
174    wantParams1.SetParam("intf7", Double::Box(int32Param));
175    wantParams1.SetParam("intf8", Byte::Box(int32Param));
176    std::size_t size = 3; // 3 means arraysize.
177    sptr<IArray> ao = new (std::nothrow) Array(size, g_IID_IBoolean);
178    if (ao != nullptr) {
179        for (std::size_t i = 0; i < size; i++) {
180            ao->Set(i, Boolean::Box(boolParam));
181        }
182        wantParams1.SetParam("intf8", ao);
183    }
184    WrapWantParams(env, wantParams1); // branch null param
185    UnwrapWantParams(env, param, wantParams1); // branch null param
186    UnwrapWantParams(env, jsObject, wantParams1); // branch not null param
187}
188
189void NapiCommonWantFuzztest4(bool boolParam, std::string &stringParam, int32_t int32Param)
190{
191    napi_value param = nullptr;
192    std::shared_ptr<OHOS::JsEnv::JsEnvironment> jsEnv = nullptr;
193    AbilityRuntime::JsRuntime::Options options;
194    auto err = JsRuntimeLite::GetInstance().CreateJsEnv(options, jsEnv);
195    napi_env env = reinterpret_cast<napi_env>(jsEnv->GetNativeEngine());
196    Want want;
197    want.SetElementName(stringParam, stringParam, stringParam, stringParam);
198    WrapWant(env, want); // wrap
199
200    UnwrapWant(env, param, want); // branch null param
201    ElementName elementName1;
202    elementName1.SetDeviceID(stringParam);
203    elementName1.SetBundleName(stringParam);
204    elementName1.SetAbilityName(stringParam);
205    elementName1.SetModuleName(stringParam);
206    napi_value jsObject = WrapElementName(env, elementName1); // branch
207    UnwrapWant(env, jsObject, want); // branch not null param
208
209    int resultCode = 0;
210    napi_value jsonObject1 = WrapAbilityResult(env, resultCode, want); // env not null
211    UnWrapAbilityResult(env, param, resultCode, want); // null param
212    UnWrapAbilityResult(env, jsonObject1, resultCode, want); // null param
213
214    napi_value jsProValue = nullptr;
215    AAFwk::WantParams wantParams1;
216    HandleNapiObject(env, param, jsProValue, stringParam, wantParams1); // param null
217    HandleNapiObject(env, jsObject, jsProValue, stringParam, wantParams1); // param not null jsProValue null.
218
219    IsSpecialObject(env, param, stringParam, stringParam, static_cast<napi_valuetype>(int32Param)); // param null
220    IsSpecialObject(env, jsObject, stringParam, stringParam, static_cast<napi_valuetype>(int32Param)); // param not null
221
222    HandleFdObject(env, param, stringParam, wantParams1); // branch null param
223    HandleRemoteObject(env, param, stringParam, wantParams1); // branch null param
224    CreateJsWant(env, want); // branch
225    CreateJsWantParams(env, wantParams1); // branch
226    napi_value object = nullptr;
227    InnerWrapJsWantParamsWantParams(env, object, stringParam, wantParams1); // branch null object
228    napi_value jsObject2 = nullptr;
229    napi_create_object(env, &jsObject2);
230    InnerWrapJsWantParamsWantParams(env, jsObject2, stringParam, wantParams1); // branch object, key not exist.
231    AAFwk::WantParams wantParams2;
232    wantParams2.SetParam("intf1", String::Box(stringParam));
233    InnerWrapJsWantParamsWantParams(env, jsObject2, "intf1", wantParams2); // branch object, key exist.
234}
235
236void NapiCommonWantFuzztest5(bool boolParam, std::string &stringParam, int32_t int32Param)
237{
238    napi_value param = nullptr;
239    std::shared_ptr<OHOS::JsEnv::JsEnvironment> jsEnv = nullptr;
240    AbilityRuntime::JsRuntime::Options options;
241    auto err = JsRuntimeLite::GetInstance().CreateJsEnv(options, jsEnv);
242    napi_env env = reinterpret_cast<napi_env>(jsEnv->GetNativeEngine());
243    napi_value nullObject = nullptr;
244    std::size_t size = 3; // 3 means arraysize.
245    sptr<IArray> ao1 = new (std::nothrow) Array(size, g_IID_IBoolean);
246    if (ao1 != nullptr) {
247        for (std::size_t i = 0; i < size; i++) {
248            ao1->Set(i, Boolean::Box(boolParam));
249        }
250    }
251    WrapJsWantParamsArray(env, nullObject, stringParam, ao1); // null object.
252    napi_value jsObject1 = nullptr;
253    napi_create_object(env, &jsObject1);
254    WrapJsWantParamsArray(env, jsObject1, stringParam, ao1); // not null object.
255
256    sptr<IArray> ao2 = new (std::nothrow) Array(size, g_IID_IChar);
257    if (ao2 != nullptr) {
258        for (std::size_t i = 0; i < size; i++) {
259            ao2->Set(i, Char::Box(int32Param));
260        }
261    }
262    WrapJsWantParamsArray(env, nullObject, stringParam, ao2); // null object.
263    napi_value jsObject2 = nullptr;
264    napi_create_object(env, &jsObject2);
265    WrapJsWantParamsArray(env, jsObject2, stringParam, ao2); // not null object.
266
267    sptr<IArray> ao3 = new (std::nothrow) Array(size, g_IID_IByte);
268    if (ao3 != nullptr) {
269        for (std::size_t i = 0; i < size; i++) {
270            ao3->Set(i, Byte::Box(int32Param));
271        }
272    }
273    WrapJsWantParamsArray(env, nullObject, stringParam, ao3); // null object.
274    napi_value jsObject3 = nullptr;
275    napi_create_object(env, &jsObject3);
276    WrapJsWantParamsArray(env, jsObject3, stringParam, ao3); // not null object.
277
278    sptr<IArray> ao4 = new (std::nothrow) Array(size, g_IID_IShort);
279    if (ao4 != nullptr) {
280        for (std::size_t i = 0; i < size; i++) {
281            ao4->Set(i, Short::Box(int32Param));
282        }
283    }
284    WrapJsWantParamsArray(env, nullObject, stringParam, ao4); // null object.
285    napi_value jsObject4 = nullptr;
286    napi_create_object(env, &jsObject4);
287    WrapJsWantParamsArray(env, jsObject4, stringParam, ao4); // not null object.
288}
289
290void NapiCommonWantFuzztest6(bool boolParam, std::string &stringParam, int32_t int32Param)
291{
292    napi_value param = nullptr;
293    std::shared_ptr<OHOS::JsEnv::JsEnvironment> jsEnv = nullptr;
294    AbilityRuntime::JsRuntime::Options options;
295    auto err = JsRuntimeLite::GetInstance().CreateJsEnv(options, jsEnv);
296    napi_env env = reinterpret_cast<napi_env>(jsEnv->GetNativeEngine());
297    napi_value nullObject = nullptr;
298    std::size_t size = 3; // 3 means arraysize.
299    sptr<IArray> ao1 = new (std::nothrow) Array(size, g_IID_ILong);
300    if (ao1 != nullptr) {
301        for (std::size_t i = 0; i < size; i++) {
302            ao1->Set(i, Long::Box(int32Param));
303        }
304    }
305    WrapJsWantParamsArray(env, nullObject, stringParam, ao1); // null object.
306    napi_value jsObject1 = nullptr;
307    napi_create_object(env, &jsObject1);
308    WrapJsWantParamsArray(env, jsObject1, stringParam, ao1); // not null object.
309
310    sptr<IArray> ao2 = new (std::nothrow) Array(size, g_IID_IFloat);
311    if (ao2 != nullptr) {
312        for (std::size_t i = 0; i < size; i++) {
313            ao2->Set(i, Float::Box(int32Param));
314        }
315    }
316    WrapJsWantParamsArray(env, nullObject, stringParam, ao2); // null object.
317    napi_value jsObject2 = nullptr;
318    napi_create_object(env, &jsObject2);
319    WrapJsWantParamsArray(env, jsObject2, stringParam, ao2); // not null object.
320
321    sptr<IArray> ao3 = new (std::nothrow) Array(size, g_IID_IDouble);
322    if (ao3 != nullptr) {
323        for (std::size_t i = 0; i < size; i++) {
324            ao3->Set(i, Double::Box(int32Param));
325        }
326    }
327    WrapJsWantParamsArray(env, nullObject, stringParam, ao3); // null object.
328    napi_value jsObject3 = nullptr;
329    napi_create_object(env, &jsObject3);
330    WrapJsWantParamsArray(env, jsObject3, stringParam, ao3); // not null object.
331
332    sptr<IArray> ao4 = new (std::nothrow) Array(size, g_IID_IString);
333    if (ao4 != nullptr) {
334        for (std::size_t i = 0; i < size; i++) {
335            ao4->Set(i, String::Box(stringParam));
336        }
337    }
338    WrapJsWantParamsArray(env, nullObject, stringParam, ao4); // null object.
339    napi_value jsObject4 = nullptr;
340    napi_create_object(env, &jsObject4);
341    WrapJsWantParamsArray(env, jsObject4, stringParam, ao4); // not null object.
342}
343
344bool DoSomethingInterestingWithMyAPI(const char* data, size_t size)
345{
346    bool boolParam = *data % ENABLE;
347    std::string stringParam(data, size);
348    int32_t int32Param = static_cast<int32_t>(GetU32Data(data));
349    NapiCommonWantFuzztest1(boolParam, stringParam, int32Param);
350    NapiCommonWantFuzztest2(boolParam, stringParam, int32Param);
351    NapiCommonWantFuzztest3(boolParam, stringParam, int32Param);
352    NapiCommonWantFuzztest4(boolParam, stringParam, int32Param);
353    NapiCommonWantFuzztest5(boolParam, stringParam, int32Param);
354    NapiCommonWantFuzztest6(boolParam, stringParam, int32Param);
355    return true;
356}
357}
358
359/* Fuzzer entry point */
360extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size)
361{
362    /* Run your code on data */
363    if (data == nullptr) {
364        return 0;
365    }
366
367    /* Validate the length of size */
368    if (size < OHOS::U32_AT_SIZE || size > OHOS::FOO_MAX_LEN) {
369        return 0;
370    }
371
372    char* ch = (char*)malloc(size + 1);
373    if (ch == nullptr) {
374        std::cout << "malloc failed." << std::endl;
375        return 0;
376    }
377
378    (void)memset_s(ch, size + 1, 0x00, size + 1);
379    if (memcpy_s(ch, size, data, size) != EOK) {
380        std::cout << "copy failed." << std::endl;
381        free(ch);
382        ch = nullptr;
383        return 0;
384    }
385
386    OHOS::DoSomethingInterestingWithMyAPI(ch, size);
387    free(ch);
388    ch = nullptr;
389    return 0;
390}
391
392