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 
42 using namespace OHOS::AAFwk;
43 using namespace OHOS::AppExecFwk;
44 using namespace OHOS::AbilityRuntime;
45 
46 namespace OHOS {
47 namespace {
48 constexpr int INPUT_ZERO = 0;
49 constexpr int INPUT_ONE = 1;
50 constexpr int INPUT_THREE = 3;
51 constexpr size_t FOO_MAX_LEN = 1024;
52 constexpr size_t U32_AT_SIZE = 4;
53 constexpr uint8_t ENABLE = 2;
54 constexpr size_t OFFSET_ZERO = 24;
55 constexpr size_t OFFSET_ONE = 16;
56 constexpr size_t OFFSET_TWO = 8;
57 }
58 
GetU32Data(const char * ptr)59 uint32_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 
GetFuzzAbilityToken()66 sptr<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 
NapiCommonWantFuzztest1(bool boolParam,std::string & stringParam,int32_t int32Param)80 void 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 
NapiCommonWantFuzztest2(bool boolParam,std::string & stringParam,int32_t int32Param)130 void 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 
NapiCommonWantFuzztest3(bool boolParam,std::string & stringParam,int32_t int32Param)146 void 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 
NapiCommonWantFuzztest4(bool boolParam,std::string & stringParam,int32_t int32Param)189 void 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 
NapiCommonWantFuzztest5(bool boolParam,std::string & stringParam,int32_t int32Param)236 void 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 
NapiCommonWantFuzztest6(bool boolParam,std::string & stringParam,int32_t int32Param)290 void 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 
DoSomethingInterestingWithMyAPI(const char * data,size_t size)344 bool 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 */
LLVMFuzzerTestOneInput(const uint8_t * data,size_t size)360 extern "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 = static_cast<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