1/*
2 * Copyright (c) 2022 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 "containersplainarray_fuzzer.h"
17
18#include "ecmascript/base/builtins_base.h"
19#include "ecmascript/containers/containers_plainarray.h"
20#include "ecmascript/containers/containers_private.h"
21#include "ecmascript/ecma_string-inl.h"
22#include "ecmascript/ecma_vm.h"
23#include "ecmascript/global_env.h"
24#include "ecmascript/js_api/js_api_plain_array.h"
25#include "ecmascript/js_handle.h"
26#include "ecmascript/napi/include/jsnapi.h"
27
28using namespace panda;
29using namespace panda::ecmascript;
30using namespace panda::ecmascript::base;
31using namespace panda::ecmascript::containers;
32
33namespace OHOS {
34    JSFunction *JSObjectCreate(JSThread *thread)
35    {
36        JSHandle<GlobalEnv> globalEnv = thread->GetEcmaVM()->GetGlobalEnv();
37        return globalEnv->GetObjectFunction().GetObject<JSFunction>();
38    }
39
40    EcmaRuntimeCallInfo *CreateEcmaRuntimeCallInfo(JSThread *thread, uint32_t numArgs)
41    {
42        auto factory = thread->GetEcmaVM()->GetFactory();
43        JSHandle<JSTaggedValue> hclass(thread, JSObjectCreate(thread));
44        JSHandle<JSTaggedValue> callee(factory->NewJSObjectByConstructor(JSHandle<JSFunction>::Cast(hclass), hclass));
45        JSHandle<JSTaggedValue> undefined = thread->GlobalConstants()->GetHandledUndefined();
46        EcmaRuntimeCallInfo *objCallInfo =
47            EcmaInterpreter::NewRuntimeCallInfo(thread, undefined, callee, undefined, numArgs);
48        return objCallInfo;
49    }
50
51    JSTaggedValue InitializePlainArrayConstructor(JSThread *thread)
52    {
53        auto factory = thread->GetEcmaVM()->GetFactory();
54        JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
55        JSHandle<JSTaggedValue> globalObject = env->GetJSGlobalObject();
56        JSHandle<JSTaggedValue> key(factory->NewFromASCII("ArkPrivate"));
57        JSHandle<JSTaggedValue> value =
58            JSObject::GetProperty(thread, JSHandle<JSTaggedValue>(globalObject), key).GetValue();
59
60        auto objCallInfo = CreateEcmaRuntimeCallInfo(thread, 6); // 6 : means the argv length
61        objCallInfo->SetFunction(JSTaggedValue::Undefined());
62        objCallInfo->SetThis(value.GetTaggedValue());
63        objCallInfo->SetCallArg(0, JSTaggedValue(static_cast<int>(ContainerTag::PlainArray)));
64        JSTaggedValue result = ContainersPrivate::Load(objCallInfo);
65        return result;
66    }
67
68    JSHandle<JSAPIPlainArray> CreateJSAPIPlainArray(JSThread *thread)
69    {
70        JSHandle<JSFunction> newTarget(thread, InitializePlainArrayConstructor(thread));
71        auto objCallInfo = CreateEcmaRuntimeCallInfo(thread, 4);
72        objCallInfo->SetFunction(newTarget.GetTaggedValue());
73        objCallInfo->SetNewTarget(newTarget.GetTaggedValue());
74        objCallInfo->SetThis(JSTaggedValue::Undefined());
75        JSTaggedValue result = ContainersPlainArray::PlainArrayConstructor(objCallInfo);
76        JSHandle<JSAPIPlainArray> array(thread, result);
77        return array;
78    }
79
80    void ContainersPlainArray_Constructor_FuzzTest(const uint8_t* data, size_t size)
81    {
82        if (data == nullptr || size <= 0) {
83            std::cout << "illegal input!";
84            return;
85        }
86        RuntimeOption option;
87        option.SetLogLevel(RuntimeOption::LOG_LEVEL::ERROR);
88        EcmaVM *vm = JSNApi::CreateJSVM(option);
89        {
90            JsiFastNativeScope scope(vm);
91            auto thread = vm->GetAssociatedJSThread();
92            uint32_t input = 0;
93            const uint32_t MAXBYTELEN = 4;
94            if (size > MAXBYTELEN) {
95                size = MAXBYTELEN;
96            }
97            if (memcpy_s(&input, MAXBYTELEN, data, size) != 0) {
98                std::cout << "memcpy_s failed!";
99                UNREACHABLE();
100            }
101            JSHandle<JSAPIPlainArray> plainArray = CreateJSAPIPlainArray(thread);
102            EcmaRuntimeCallInfo *callInfo = CreateEcmaRuntimeCallInfo(thread, 6); // 6 : means the argv length
103            callInfo->SetFunction(JSTaggedValue::Undefined());
104            callInfo->SetThis(plainArray.GetTaggedValue());
105            callInfo->SetCallArg(0, JSTaggedValue(input));
106            ContainersPlainArray::PlainArrayConstructor(callInfo);
107        }
108        JSNApi::DestroyJSVM(vm);
109    }
110
111    void ContainersPlainArray_Add_Has_FuzzTest(const uint8_t* data, size_t size)
112    {
113        if (data == nullptr || size <= 0) {
114            std::cout << "illegal input!";
115            return;
116        }
117        RuntimeOption option;
118        option.SetLogLevel(RuntimeOption::LOG_LEVEL::ERROR);
119        EcmaVM *vm = JSNApi::CreateJSVM(option);
120        {
121            JsiFastNativeScope scope(vm);
122            auto thread = vm->GetAssociatedJSThread();
123            auto factory = vm->GetFactory();
124
125            uint32_t inputNum = 0;
126            std::string inputStr(data, data + size);
127            const uint32_t MAXBYTELEN = 4;
128            if (size > MAXBYTELEN) {
129                size = MAXBYTELEN;
130            }
131            if (memcpy_s(&inputNum, MAXBYTELEN, data, size) != 0) {
132                std::cout << "memcpy_s failed!";
133                UNREACHABLE();
134            }
135            JSHandle<JSAPIPlainArray> plainArray = CreateJSAPIPlainArray(thread);
136            const uint32_t addTimes = 3;
137            for (uint32_t i = 0; i < addTimes; i++) {
138                JSHandle<EcmaString> inputEcmaStr = factory->NewFromStdString(inputStr);
139                EcmaRuntimeCallInfo *callInfo = CreateEcmaRuntimeCallInfo(thread, 8); // 8 : means the argv length
140                callInfo->SetFunction(JSTaggedValue::Undefined());
141                callInfo->SetThis(plainArray.GetTaggedValue());
142                callInfo->SetCallArg(0, JSTaggedValue(static_cast<uint32_t>(inputNum + i))); // set key
143                callInfo->SetCallArg(1, inputEcmaStr.GetTaggedValue()); // set value
144                ContainersPlainArray::Add(callInfo);
145            }
146
147            for (uint32_t i = 0; i < addTimes; i++) {
148                EcmaRuntimeCallInfo *callInfo = CreateEcmaRuntimeCallInfo(thread, 6); // 6 : means the argv length
149                callInfo->SetFunction(JSTaggedValue::Undefined());
150                callInfo->SetThis(plainArray.GetTaggedValue());
151                callInfo->SetCallArg(0, JSTaggedValue(static_cast<uint32_t>(inputNum + i)));
152                ContainersPlainArray::Has(callInfo);  // expected to return true
153            }
154        }
155        JSNApi::DestroyJSVM(vm);
156    }
157
158    void ContainersPlainArray_Clone_FuzzTest(const uint8_t* data, size_t size)
159    {
160        if (data == nullptr || size <= 0) {
161            std::cout << "illegal input!";
162            return;
163        }
164        RuntimeOption option;
165        option.SetLogLevel(RuntimeOption::LOG_LEVEL::ERROR);
166        EcmaVM *vm = JSNApi::CreateJSVM(option);
167        {
168            JsiFastNativeScope scope(vm);
169            auto thread = vm->GetAssociatedJSThread();
170            auto factory = vm->GetFactory();
171
172            uint32_t inputNum = 0;
173            std::string inputStr(data, data + size);
174            const uint32_t MAXBYTELEN = 4;
175            if (size > MAXBYTELEN) {
176                size = MAXBYTELEN;
177            }
178            if (memcpy_s(&inputNum, MAXBYTELEN, data, size) != 0) {
179                std::cout << "memcpy_s failed!";
180                UNREACHABLE();
181            }
182            JSHandle<JSAPIPlainArray> plainArray = CreateJSAPIPlainArray(thread);
183            JSHandle<EcmaString> inputEcmaStr = factory->NewFromStdString(inputStr);
184            EcmaRuntimeCallInfo *callInfo = CreateEcmaRuntimeCallInfo(thread, 8); // 8 : means the argv length
185            callInfo->SetFunction(JSTaggedValue::Undefined());
186            callInfo->SetThis(plainArray.GetTaggedValue());
187            callInfo->SetCallArg(0, JSTaggedValue(static_cast<uint32_t>(inputNum)));
188            callInfo->SetCallArg(1, inputEcmaStr.GetTaggedValue());
189            ContainersPlainArray::Add(callInfo);
190
191            EcmaRuntimeCallInfo *cfForClone = CreateEcmaRuntimeCallInfo(thread, 4); // 4 : means the argv length
192            cfForClone->SetFunction(JSTaggedValue::Undefined());
193            cfForClone->SetThis(plainArray.GetTaggedValue());
194            ContainersPlainArray::Clone(cfForClone); // expected to return new plain array
195        }
196        JSNApi::DestroyJSVM(vm);
197    }
198
199    void ContainersPlainArray_Clear_FuzzTest(const uint8_t* data, size_t size)
200    {
201        if (data == nullptr || size <= 0) {
202            std::cout << "illegal input!";
203            return;
204        }
205        RuntimeOption option;
206        option.SetLogLevel(RuntimeOption::LOG_LEVEL::ERROR);
207        EcmaVM *vm = JSNApi::CreateJSVM(option);
208        {
209            JsiFastNativeScope scope(vm);
210            auto thread = vm->GetAssociatedJSThread();
211            auto factory = vm->GetFactory();
212
213            uint32_t inputNum = 0;
214            std::string inputStr(data, data + size);
215            const uint32_t MAXBYTELEN = 4;
216            if (size > MAXBYTELEN) {
217                size = MAXBYTELEN;
218            }
219            if (memcpy_s(&inputNum, MAXBYTELEN, data, size) != 0) {
220                std::cout << "memcpy_s failed!";
221                UNREACHABLE();
222            }
223            JSHandle<JSAPIPlainArray> plainArray = CreateJSAPIPlainArray(thread);
224            JSHandle<EcmaString> inputEcmaStr = factory->NewFromStdString(inputStr);
225            EcmaRuntimeCallInfo *callInfo = CreateEcmaRuntimeCallInfo(thread, 8); // 8 : means the argv length
226            callInfo->SetFunction(JSTaggedValue::Undefined());
227            callInfo->SetThis(plainArray.GetTaggedValue());
228            callInfo->SetCallArg(0, JSTaggedValue(static_cast<uint32_t>(inputNum)));
229            callInfo->SetCallArg(1, inputEcmaStr.GetTaggedValue());
230            ContainersPlainArray::Add(callInfo);
231
232            EcmaRuntimeCallInfo *cfForClear = CreateEcmaRuntimeCallInfo(thread, 4); // 4 : means the argv length
233            cfForClear->SetFunction(JSTaggedValue::Undefined());
234            cfForClear->SetThis(plainArray.GetTaggedValue());
235            ContainersPlainArray::Clear(cfForClear); // expected to return true
236        }
237        JSNApi::DestroyJSVM(vm);
238    }
239
240    void ContainersPlainArray_Get_FuzzTest(const uint8_t* data, size_t size)
241    {
242        if (data == nullptr || size <= 0) {
243            std::cout << "illegal input!";
244            return;
245        }
246        RuntimeOption option;
247        option.SetLogLevel(RuntimeOption::LOG_LEVEL::ERROR);
248        EcmaVM *vm = JSNApi::CreateJSVM(option);
249        {
250            JsiFastNativeScope scope(vm);
251            auto thread = vm->GetAssociatedJSThread();
252            auto factory = vm->GetFactory();
253
254            uint32_t inputNum = 0;
255            std::string inputStr(data, data + size);
256            const uint32_t MAXBYTELEN = 4;
257            if (size > MAXBYTELEN) {
258                size = MAXBYTELEN;
259            }
260            if (memcpy_s(&inputNum, MAXBYTELEN, data, size) != 0) {
261                std::cout << "memcpy_s failed!";
262                UNREACHABLE();
263            }
264            JSHandle<JSAPIPlainArray> plainArray = CreateJSAPIPlainArray(thread);
265            JSHandle<EcmaString> inputEcmaStr = factory->NewFromStdString(inputStr);
266            EcmaRuntimeCallInfo *callInfo = CreateEcmaRuntimeCallInfo(thread, 8); // 8 : means the argv length
267            callInfo->SetFunction(JSTaggedValue::Undefined());
268            callInfo->SetThis(plainArray.GetTaggedValue());
269            callInfo->SetCallArg(0, JSTaggedValue(static_cast<uint32_t>(inputNum)));
270            callInfo->SetCallArg(1, inputEcmaStr.GetTaggedValue());
271            ContainersPlainArray::Add(callInfo);
272
273            EcmaRuntimeCallInfo *cfForGet = CreateEcmaRuntimeCallInfo(thread, 6); // 6 : means the argv length
274            cfForGet->SetFunction(JSTaggedValue::Undefined());
275            cfForGet->SetThis(plainArray.GetTaggedValue());
276            cfForGet->SetCallArg(0, JSTaggedValue(static_cast<uint32_t>(inputNum))); // set key get value
277            ContainersPlainArray::Get(cfForGet); // expected to return value
278        }
279        JSNApi::DestroyJSVM(vm);
280    }
281
282    void ContainersPlainArray_GetIteratorObj_FuzzTest(const uint8_t* data, size_t size)
283    {
284        if (data == nullptr || size <= 0) {
285            std::cout << "illegal input!";
286            return;
287        }
288        RuntimeOption option;
289        option.SetLogLevel(RuntimeOption::LOG_LEVEL::ERROR);
290        EcmaVM *vm = JSNApi::CreateJSVM(option);
291        {
292            JsiFastNativeScope scope(vm);
293            auto thread = vm->GetAssociatedJSThread();
294            auto factory = vm->GetFactory();
295
296            uint32_t inputNum = 0;
297            std::string inputStr(data, data + size);
298            const uint32_t MAXBYTELEN = 4;
299            if (size > MAXBYTELEN) {
300                size = MAXBYTELEN;
301            }
302            if (memcpy_s(&inputNum, MAXBYTELEN, data, size) != 0) {
303                std::cout << "memcpy_s failed!";
304                UNREACHABLE();
305            }
306            JSHandle<JSAPIPlainArray> plainArray = CreateJSAPIPlainArray(thread);
307            JSHandle<EcmaString> inputEcmaStr = factory->NewFromStdString(inputStr);
308            EcmaRuntimeCallInfo *callInfo = CreateEcmaRuntimeCallInfo(thread, 8); // 8 : means the argv length
309            callInfo->SetFunction(JSTaggedValue::Undefined());
310            callInfo->SetThis(plainArray.GetTaggedValue());
311            callInfo->SetCallArg(0, JSTaggedValue(static_cast<uint32_t>(inputNum)));
312            callInfo->SetCallArg(1, inputEcmaStr.GetTaggedValue());
313            ContainersPlainArray::Add(callInfo);
314
315            EcmaRuntimeCallInfo *cfForGetIteratorObj =
316                CreateEcmaRuntimeCallInfo(thread, 4); // 4 : means the argv length
317            cfForGetIteratorObj->SetFunction(JSTaggedValue::Undefined());
318            cfForGetIteratorObj->SetThis(plainArray.GetTaggedValue());
319            ContainersPlainArray::GetIteratorObj(cfForGetIteratorObj); // expected to return iterator
320        }
321        JSNApi::DestroyJSVM(vm);
322    }
323
324    static JSTaggedValue TestForEachFunc(EcmaRuntimeCallInfo *argv)
325    {
326        JSThread *thread = argv->GetThread();
327        JSHandle<JSTaggedValue> key = BuiltinsBase::GetCallArg(argv, 0);  // 0 means the value
328        JSHandle<JSTaggedValue> value = BuiltinsBase::GetCallArg(argv, 1); // 1 means the value
329        JSHandle<JSAPIPlainArray> plainArray(BuiltinsBase::GetCallArg(argv, 2)); // 2 means the value
330        JSHandle<JSTaggedValue> newValue(thread, value.GetTaggedValue());
331        JSAPIPlainArray::Add(thread, plainArray, key, newValue);
332        return JSTaggedValue::True();
333    }
334
335    void ContainersPlainArray_ForEach_FuzzTest(const uint8_t* data, size_t size)
336    {
337        if (data == nullptr || size <= 0) {
338            std::cout << "illegal input!";
339            return;
340        }
341        RuntimeOption option;
342        option.SetLogLevel(RuntimeOption::LOG_LEVEL::ERROR);
343        EcmaVM *vm = JSNApi::CreateJSVM(option);
344        {
345            JsiFastNativeScope scope(vm);
346            auto thread = vm->GetAssociatedJSThread();
347            auto factory = vm->GetFactory();
348            JSHandle<GlobalEnv> env = vm->GetGlobalEnv();
349
350            uint32_t inputNum = 0;
351            std::string inputStr(data, data + size);
352            const uint32_t MAXBYTELEN = 4;
353            if (size > MAXBYTELEN) {
354                size = MAXBYTELEN;
355            }
356            if (memcpy_s(&inputNum, MAXBYTELEN, data, size) != 0) {
357                std::cout << "memcpy_s failed!";
358                UNREACHABLE();
359            }
360            JSHandle<JSAPIPlainArray> plainArray = CreateJSAPIPlainArray(thread);
361            JSHandle<EcmaString> inputEcmaStr = factory->NewFromStdString(inputStr);
362            EcmaRuntimeCallInfo *callInfo = CreateEcmaRuntimeCallInfo(thread, 8); // 8 : means the argv length
363            callInfo->SetFunction(JSTaggedValue::Undefined());
364            callInfo->SetThis(plainArray.GetTaggedValue());
365            callInfo->SetCallArg(0, JSTaggedValue(static_cast<uint32_t>(inputNum)));
366            callInfo->SetCallArg(1, inputEcmaStr.GetTaggedValue());
367            ContainersPlainArray::Add(callInfo);
368
369            JSHandle<JSAPIPlainArray> thisArg = CreateJSAPIPlainArray(thread);
370            JSHandle<JSFunction> cbFunc = factory->NewJSFunction(env, reinterpret_cast<void *>(TestForEachFunc));
371            EcmaRuntimeCallInfo *cfForForEach = CreateEcmaRuntimeCallInfo(thread, 8); // 8 : means the argv length
372            cfForForEach->SetFunction(JSTaggedValue::Undefined());
373            cfForForEach->SetThis(plainArray.GetTaggedValue());
374            cfForForEach->SetCallArg(0, cbFunc.GetTaggedValue());
375            cfForForEach->SetCallArg(1, thisArg.GetTaggedValue());
376            ContainersPlainArray::ForEach(cfForForEach); // expected to return undefined
377        }
378        JSNApi::DestroyJSVM(vm);
379    }
380
381    void ContainersPlainArray_ToString_FuzzTest(const uint8_t* data, size_t size)
382    {
383        if (data == nullptr || size <= 0) {
384            std::cout << "illegal input!";
385            return;
386        }
387        RuntimeOption option;
388        option.SetLogLevel(RuntimeOption::LOG_LEVEL::ERROR);
389        EcmaVM *vm = JSNApi::CreateJSVM(option);
390        {
391            JsiFastNativeScope scope(vm);
392            auto thread = vm->GetAssociatedJSThread();
393            auto factory = vm->GetFactory();
394
395            uint32_t inputNum = 0;
396            std::string inputStr(data, data + size);
397            const uint32_t MAXBYTELEN = 4;
398            if (size > MAXBYTELEN) {
399                size = MAXBYTELEN;
400            }
401            if (memcpy_s(&inputNum, MAXBYTELEN, data, size) != 0) {
402                std::cout << "memcpy_s failed!";
403                UNREACHABLE();
404            }
405            JSHandle<JSAPIPlainArray> plainArray = CreateJSAPIPlainArray(thread);
406            JSHandle<EcmaString> inputEcmaStr = factory->NewFromStdString(inputStr);
407            EcmaRuntimeCallInfo *callInfo = CreateEcmaRuntimeCallInfo(thread, 8); // 8 : means the argv length
408            callInfo->SetFunction(JSTaggedValue::Undefined());
409            callInfo->SetThis(plainArray.GetTaggedValue());
410            callInfo->SetCallArg(0, JSTaggedValue(static_cast<uint32_t>(inputNum)));
411            callInfo->SetCallArg(1, inputEcmaStr.GetTaggedValue());
412            ContainersPlainArray::Add(callInfo);
413
414            EcmaRuntimeCallInfo *cfForToString = CreateEcmaRuntimeCallInfo(thread, 4); // 4 : means the argv length
415            cfForToString->SetFunction(JSTaggedValue::Undefined());
416            cfForToString->SetThis(plainArray.GetTaggedValue());
417            ContainersPlainArray::ToString(cfForToString); // expected to return string object
418        }
419        JSNApi::DestroyJSVM(vm);
420    }
421
422    void ContainersPlainArray_GetIndexOfKey_FuzzTest(const uint8_t* data, size_t size)
423    {
424        if (data == nullptr || size <= 0) {
425            std::cout << "illegal input!";
426            return;
427        }
428        RuntimeOption option;
429        option.SetLogLevel(RuntimeOption::LOG_LEVEL::ERROR);
430        EcmaVM *vm = JSNApi::CreateJSVM(option);
431        {
432            JsiFastNativeScope scope(vm);
433            auto thread = vm->GetAssociatedJSThread();
434            auto factory = vm->GetFactory();
435
436            uint32_t inputNum = 0;
437            std::string inputStr(data, data + size);
438            const uint32_t MAXBYTELEN = 4;
439            if (size > MAXBYTELEN) {
440                size = MAXBYTELEN;
441            }
442            if (memcpy_s(&inputNum, MAXBYTELEN, data, size) != 0) {
443                std::cout << "memcpy_s failed!";
444                UNREACHABLE();
445            }
446            JSHandle<JSAPIPlainArray> plainArray = CreateJSAPIPlainArray(thread);
447            JSHandle<EcmaString> inputEcmaStr = factory->NewFromStdString(inputStr);
448            EcmaRuntimeCallInfo *callInfo = CreateEcmaRuntimeCallInfo(thread, 8); // 8 : means the argv length
449            callInfo->SetFunction(JSTaggedValue::Undefined());
450            callInfo->SetThis(plainArray.GetTaggedValue());
451            callInfo->SetCallArg(0, JSTaggedValue(static_cast<uint32_t>(inputNum)));
452            callInfo->SetCallArg(1, inputEcmaStr.GetTaggedValue());
453            ContainersPlainArray::Add(callInfo);
454
455            EcmaRuntimeCallInfo *cfForGetIndexOfKey =
456                CreateEcmaRuntimeCallInfo(thread, 6); // 6 : means the argv length
457            cfForGetIndexOfKey->SetFunction(JSTaggedValue::Undefined());
458            cfForGetIndexOfKey->SetThis(plainArray.GetTaggedValue());
459            cfForGetIndexOfKey->SetCallArg(0, inputEcmaStr.GetTaggedValue()); // value
460            ContainersPlainArray::GetIndexOfKey(cfForGetIndexOfKey); // expected to return the index of key
461        }
462        JSNApi::DestroyJSVM(vm);
463    }
464
465    void ContainersPlainArray_GetIndexOfValue_FuzzTest(const uint8_t* data, size_t size)
466    {
467        if (data == nullptr || size <= 0) {
468            std::cout << "illegal input!";
469            return;
470        }
471        RuntimeOption option;
472        option.SetLogLevel(RuntimeOption::LOG_LEVEL::ERROR);
473        EcmaVM *vm = JSNApi::CreateJSVM(option);
474        {
475            JsiFastNativeScope scope(vm);
476            auto thread = vm->GetAssociatedJSThread();
477            auto factory = vm->GetFactory();
478
479            uint32_t inputNum = 0;
480            std::string inputStr(data, data + size);
481            const uint32_t MAXBYTELEN = 4;
482            if (size > MAXBYTELEN) {
483                size = MAXBYTELEN;
484            }
485            if (memcpy_s(&inputNum, MAXBYTELEN, data, size) != 0) {
486                std::cout << "memcpy_s failed!";
487                UNREACHABLE();
488            }
489            JSHandle<JSAPIPlainArray> plainArray = CreateJSAPIPlainArray(thread);
490            JSHandle<EcmaString> inputEcmaStr = factory->NewFromStdString(inputStr);
491            EcmaRuntimeCallInfo *callInfo = CreateEcmaRuntimeCallInfo(thread, 8); // 8 : means the argv length
492            callInfo->SetFunction(JSTaggedValue::Undefined());
493            callInfo->SetThis(plainArray.GetTaggedValue());
494            callInfo->SetCallArg(0, JSTaggedValue(static_cast<uint32_t>(inputNum)));
495            callInfo->SetCallArg(1, inputEcmaStr.GetTaggedValue());
496            ContainersPlainArray::Add(callInfo);
497
498            EcmaRuntimeCallInfo *cfForGetIndexOfValue =
499                CreateEcmaRuntimeCallInfo(thread, 6); // 6 : means the argv length
500            cfForGetIndexOfValue->SetFunction(JSTaggedValue::Undefined());
501            cfForGetIndexOfValue->SetThis(plainArray.GetTaggedValue());
502            cfForGetIndexOfValue->SetCallArg(0, JSTaggedValue(static_cast<uint32_t>(inputNum))); // key
503            ContainersPlainArray::GetIndexOfValue(cfForGetIndexOfValue); // expected to return the index of value
504        }
505        JSNApi::DestroyJSVM(vm);
506    }
507
508    void ContainersPlainArray_IsEmpty_FuzzTest(const uint8_t* data, size_t size)
509    {
510        if (data == nullptr || size <= 0) {
511            std::cout << "illegal input!";
512            return;
513        }
514        RuntimeOption option;
515        option.SetLogLevel(RuntimeOption::LOG_LEVEL::ERROR);
516        EcmaVM *vm = JSNApi::CreateJSVM(option);
517        {
518            JsiFastNativeScope scope(vm);
519            auto thread = vm->GetAssociatedJSThread();
520            auto factory = vm->GetFactory();
521
522            uint32_t inputNum = 0;
523            std::string inputStr(data, data + size);
524            const uint32_t MAXBYTELEN = 4;
525            if (size > MAXBYTELEN) {
526                size = MAXBYTELEN;
527            }
528            if (memcpy_s(&inputNum, MAXBYTELEN, data, size) != 0) {
529                std::cout << "memcpy_s failed!";
530                UNREACHABLE();
531            }
532            JSHandle<JSAPIPlainArray> plainArray = CreateJSAPIPlainArray(thread);
533            JSHandle<EcmaString> inputEcmaStr = factory->NewFromStdString(inputStr);
534            EcmaRuntimeCallInfo *callInfo = CreateEcmaRuntimeCallInfo(thread, 8); // 8 : means the argv length
535            callInfo->SetFunction(JSTaggedValue::Undefined());
536            callInfo->SetThis(plainArray.GetTaggedValue());
537            callInfo->SetCallArg(0, JSTaggedValue(static_cast<uint32_t>(inputNum)));
538            callInfo->SetCallArg(1, inputEcmaStr.GetTaggedValue());
539            ContainersPlainArray::Add(callInfo);
540
541            EcmaRuntimeCallInfo *cfForIsEmpty = CreateEcmaRuntimeCallInfo(thread, 4); // 4 : means the argv length
542            cfForIsEmpty->SetFunction(JSTaggedValue::Undefined());
543            cfForIsEmpty->SetThis(plainArray.GetTaggedValue());
544            ContainersPlainArray::IsEmpty(cfForIsEmpty); // expected to return true or false
545        }
546        JSNApi::DestroyJSVM(vm);
547    }
548
549    void ContainersPlainArray_GetKeyAt_FuzzTest(const uint8_t* data, size_t size)
550    {
551        if (data == nullptr || size <= 0) {
552            std::cout << "illegal input!";
553            return;
554        }
555        RuntimeOption option;
556        option.SetLogLevel(RuntimeOption::LOG_LEVEL::ERROR);
557        EcmaVM *vm = JSNApi::CreateJSVM(option);
558        {
559            JsiFastNativeScope scope(vm);
560            auto thread = vm->GetAssociatedJSThread();
561            auto factory = vm->GetFactory();
562
563            uint32_t inputNum = 0;
564            std::string inputStr(data, data + size);
565            const uint32_t MAXBYTELEN = 4;
566            if (size > MAXBYTELEN) {
567                size = MAXBYTELEN;
568            }
569            if (memcpy_s(&inputNum, MAXBYTELEN, data, size) != 0) {
570                std::cout << "memcpy_s failed!";
571                UNREACHABLE();
572            }
573            JSHandle<JSAPIPlainArray> plainArray = CreateJSAPIPlainArray(thread);
574            JSHandle<EcmaString> inputEcmaStr = factory->NewFromStdString(inputStr);
575            EcmaRuntimeCallInfo *callInfo = CreateEcmaRuntimeCallInfo(thread, 8); // 8 : means the argv length
576            callInfo->SetFunction(JSTaggedValue::Undefined());
577            callInfo->SetThis(plainArray.GetTaggedValue());
578            callInfo->SetCallArg(0, JSTaggedValue(static_cast<uint32_t>(inputNum)));
579            callInfo->SetCallArg(1, inputEcmaStr.GetTaggedValue());
580            ContainersPlainArray::Add(callInfo);
581
582            EcmaRuntimeCallInfo *cfForGetKeyAt = CreateEcmaRuntimeCallInfo(thread, 6); // 6 : means the argv length
583            cfForGetKeyAt->SetFunction(JSTaggedValue::Undefined());
584            cfForGetKeyAt->SetThis(plainArray.GetTaggedValue());
585            cfForGetKeyAt->SetCallArg(0, inputEcmaStr.GetTaggedValue()); // value
586            ContainersPlainArray::GetKeyAt(cfForGetKeyAt); // expected to return the key
587        }
588        JSNApi::DestroyJSVM(vm);
589    }
590
591    void ContainersPlainArray_Remove_FuzzTest(const uint8_t* data, size_t size)
592    {
593        if (data == nullptr || size <= 0) {
594            std::cout << "illegal input!";
595            return;
596        }
597        RuntimeOption option;
598        option.SetLogLevel(RuntimeOption::LOG_LEVEL::ERROR);
599        EcmaVM *vm = JSNApi::CreateJSVM(option);
600        {
601            JsiFastNativeScope scope(vm);
602            auto thread = vm->GetAssociatedJSThread();
603            auto factory = vm->GetFactory();
604
605            uint32_t inputNum = 0;
606            std::string inputStr(data, data + size);
607            const uint32_t MAXBYTELEN = 4;
608            if (size > MAXBYTELEN) {
609                size = MAXBYTELEN;
610            }
611            if (memcpy_s(&inputNum, MAXBYTELEN, data, size) != 0) {
612                std::cout << "memcpy_s failed!";
613                UNREACHABLE();
614            }
615            JSHandle<JSAPIPlainArray> plainArray = CreateJSAPIPlainArray(thread);
616            JSHandle<EcmaString> inputEcmaStr = factory->NewFromStdString(inputStr);
617            EcmaRuntimeCallInfo *callInfo = CreateEcmaRuntimeCallInfo(thread, 8); // 8 : means the argv length
618            callInfo->SetFunction(JSTaggedValue::Undefined());
619            callInfo->SetThis(plainArray.GetTaggedValue());
620            callInfo->SetCallArg(0, JSTaggedValue(static_cast<uint32_t>(inputNum)));
621            callInfo->SetCallArg(1, inputEcmaStr.GetTaggedValue());
622            ContainersPlainArray::Add(callInfo);
623
624            EcmaRuntimeCallInfo *cfForRemove = CreateEcmaRuntimeCallInfo(thread, 6); // 6 : means the argv length
625            cfForRemove->SetFunction(JSTaggedValue::Undefined());
626            cfForRemove->SetThis(plainArray.GetTaggedValue());
627            cfForRemove->SetCallArg(0, JSTaggedValue(static_cast<uint32_t>(inputNum)));
628            ContainersPlainArray::Remove(cfForRemove); // expected to return the value
629        }
630        JSNApi::DestroyJSVM(vm);
631    }
632
633    void ContainersPlainArray_RemoveAt_FuzzTest(const uint8_t* data, size_t size)
634    {
635        if (data == nullptr || size <= 0) {
636            std::cout << "illegal input!";
637            return;
638        }
639        RuntimeOption option;
640        option.SetLogLevel(RuntimeOption::LOG_LEVEL::ERROR);
641        EcmaVM *vm = JSNApi::CreateJSVM(option);
642        {
643            JsiFastNativeScope scope(vm);
644            auto thread = vm->GetAssociatedJSThread();
645            auto factory = vm->GetFactory();
646
647            uint32_t inputNum = 0;
648            std::string inputStr(data, data + size);
649            const uint32_t MAXBYTELEN = 4;
650            if (size > MAXBYTELEN) {
651                size = MAXBYTELEN;
652            }
653            if (memcpy_s(&inputNum, MAXBYTELEN, data, size) != 0) {
654                std::cout << "memcpy_s failed!";
655                UNREACHABLE();
656            }
657            JSHandle<JSAPIPlainArray> plainArray = CreateJSAPIPlainArray(thread);
658            JSHandle<EcmaString> inputEcmaStr = factory->NewFromStdString(inputStr);
659            EcmaRuntimeCallInfo *callInfo = CreateEcmaRuntimeCallInfo(thread, 8); // 8 : means the argv length
660            callInfo->SetFunction(JSTaggedValue::Undefined());
661            callInfo->SetThis(plainArray.GetTaggedValue());
662            callInfo->SetCallArg(0, JSTaggedValue(static_cast<uint32_t>(inputNum)));
663            callInfo->SetCallArg(1, inputEcmaStr.GetTaggedValue());
664            ContainersPlainArray::Add(callInfo);
665
666            EcmaRuntimeCallInfo *cfForRemoveAt = CreateEcmaRuntimeCallInfo(thread, 6); // 6 : means the argv length
667            cfForRemoveAt->SetFunction(JSTaggedValue::Undefined());
668            cfForRemoveAt->SetThis(plainArray.GetTaggedValue());
669            cfForRemoveAt->SetCallArg(0, JSTaggedValue(static_cast<uint32_t>(inputNum)));
670            ContainersPlainArray::RemoveAt(cfForRemoveAt); // expected to return the value
671        }
672        JSNApi::DestroyJSVM(vm);
673    }
674
675    void ContainersPlainArray_RemoveRangeFrom_FuzzTest(const uint8_t* data, size_t size)
676    {
677        if (data == nullptr || size <= 0) {
678            std::cout << "illegal input!";
679            return;
680        }
681        RuntimeOption option;
682        option.SetLogLevel(RuntimeOption::LOG_LEVEL::ERROR);
683        EcmaVM *vm = JSNApi::CreateJSVM(option);
684        {
685            JsiFastNativeScope scope(vm);
686            auto thread = vm->GetAssociatedJSThread();
687            auto factory = vm->GetFactory();
688
689            uint32_t inputNum = 0;
690            std::string inputStr(data, data + size);
691            const uint32_t MAXBYTELEN = 4;
692            if (size > MAXBYTELEN) {
693                size = MAXBYTELEN;
694            }
695            if (memcpy_s(&inputNum, MAXBYTELEN, data, size) != 0) {
696                std::cout << "memcpy_s failed!";
697                UNREACHABLE();
698            }
699            JSHandle<JSAPIPlainArray> plainArray = CreateJSAPIPlainArray(thread);
700            JSHandle<EcmaString> inputEcmaStr = factory->NewFromStdString(inputStr);
701            EcmaRuntimeCallInfo *callInfo = CreateEcmaRuntimeCallInfo(thread, 8); // 8 : means the argv length
702            callInfo->SetFunction(JSTaggedValue::Undefined());
703            callInfo->SetThis(plainArray.GetTaggedValue());
704            callInfo->SetCallArg(0, JSTaggedValue(static_cast<uint32_t>(inputNum)));
705            callInfo->SetCallArg(1, inputEcmaStr.GetTaggedValue());
706            ContainersPlainArray::Add(callInfo);
707
708            EcmaRuntimeCallInfo *cfForRemoveRangeFrom =
709                CreateEcmaRuntimeCallInfo(thread, 8); // 8 : means the argv length
710            cfForRemoveRangeFrom->SetFunction(JSTaggedValue::Undefined());
711            cfForRemoveRangeFrom->SetThis(plainArray.GetTaggedValue());
712            cfForRemoveRangeFrom->SetCallArg(0, JSTaggedValue(0)); // set index as the head of array
713            cfForRemoveRangeFrom->SetCallArg(1, JSTaggedValue(static_cast<uint32_t>(inputNum))); // number to delete
714            ContainersPlainArray::RemoveRangeFrom(cfForRemoveRangeFrom); // expected to return the safe size
715        }
716        JSNApi::DestroyJSVM(vm);
717    }
718
719    void ContainersPlainArray_SetValueAt_FuzzTest(const uint8_t* data, size_t size)
720    {
721        if (data == nullptr || size <= 0) {
722            std::cout << "illegal input!";
723            return;
724        }
725        RuntimeOption option;
726        option.SetLogLevel(RuntimeOption::LOG_LEVEL::ERROR);
727        EcmaVM *vm = JSNApi::CreateJSVM(option);
728        {
729            JsiFastNativeScope scope(vm);
730            auto thread = vm->GetAssociatedJSThread();
731            auto factory = vm->GetFactory();
732
733            uint32_t inputNum = 0;
734            std::string inputStr(data, data + size);
735            const uint32_t MAXBYTELEN = 4;
736            if (size > MAXBYTELEN) {
737                size = MAXBYTELEN;
738            }
739            if (memcpy_s(&inputNum, MAXBYTELEN, data, size) != 0) {
740                std::cout << "memcpy_s failed!";
741                UNREACHABLE();
742            }
743            JSHandle<JSAPIPlainArray> plainArray = CreateJSAPIPlainArray(thread);
744            JSHandle<EcmaString> inputEcmaStr = factory->NewFromStdString(inputStr);
745            EcmaRuntimeCallInfo *callInfo = CreateEcmaRuntimeCallInfo(thread, 8); // 8 : means the argv length
746            callInfo->SetFunction(JSTaggedValue::Undefined());
747            callInfo->SetThis(plainArray.GetTaggedValue());
748            callInfo->SetCallArg(0, JSTaggedValue(static_cast<uint32_t>(inputNum)));
749            callInfo->SetCallArg(1, inputEcmaStr.GetTaggedValue());
750            ContainersPlainArray::Add(callInfo);
751
752            EcmaRuntimeCallInfo *cfForSetValueAt = CreateEcmaRuntimeCallInfo(thread, 8); // 8 : means the argv length
753            cfForSetValueAt->SetFunction(JSTaggedValue::Undefined());
754            cfForSetValueAt->SetThis(plainArray.GetTaggedValue());
755            cfForSetValueAt->SetCallArg(0, JSTaggedValue(static_cast<uint32_t>(inputNum))); // set index to set
756            cfForSetValueAt->SetCallArg(1, JSTaggedValue(static_cast<uint32_t>(inputNum))); // set new value
757            ContainersPlainArray::SetValueAt(cfForSetValueAt); // expected to return undefined
758        }
759        JSNApi::DestroyJSVM(vm);
760    }
761
762    void ContainersPlainArray_GetValueAt_FuzzTest(const uint8_t* data, size_t size)
763    {
764        if (data == nullptr || size <= 0) {
765            std::cout << "illegal input!";
766            return;
767        }
768        RuntimeOption option;
769        option.SetLogLevel(RuntimeOption::LOG_LEVEL::ERROR);
770        EcmaVM *vm = JSNApi::CreateJSVM(option);
771        {
772            JsiFastNativeScope scope(vm);
773            auto thread = vm->GetAssociatedJSThread();
774            auto factory = vm->GetFactory();
775
776            uint32_t inputNum = 0;
777            std::string inputStr(data, data + size);
778            const uint32_t MAXBYTELEN = 4;
779            if (size > MAXBYTELEN) {
780                size = MAXBYTELEN;
781            }
782            if (memcpy_s(&inputNum, MAXBYTELEN, data, size) != 0) {
783                std::cout << "memcpy_s failed!";
784                UNREACHABLE();
785            }
786            JSHandle<JSAPIPlainArray> plainArray = CreateJSAPIPlainArray(thread);
787            JSHandle<EcmaString> inputEcmaStr = factory->NewFromStdString(inputStr);
788            EcmaRuntimeCallInfo *callInfo = CreateEcmaRuntimeCallInfo(thread, 8); // 8 : means the argv length
789            callInfo->SetFunction(JSTaggedValue::Undefined());
790            callInfo->SetThis(plainArray.GetTaggedValue());
791            callInfo->SetCallArg(0, JSTaggedValue(static_cast<uint32_t>(inputNum)));
792            callInfo->SetCallArg(1, inputEcmaStr.GetTaggedValue());
793            ContainersPlainArray::Add(callInfo);
794
795            EcmaRuntimeCallInfo *cfForGetValueAt = CreateEcmaRuntimeCallInfo(thread, 6); // 6 : means the argv length
796            cfForGetValueAt->SetFunction(JSTaggedValue::Undefined());
797            cfForGetValueAt->SetThis(plainArray.GetTaggedValue());
798            cfForGetValueAt->SetCallArg(0, JSTaggedValue(static_cast<uint32_t>(inputNum))); // set index to get
799            ContainersPlainArray::GetValueAt(cfForGetValueAt); // expected to return value
800        }
801        JSNApi::DestroyJSVM(vm);
802    }
803
804    void ContainersPlainArray_GetSize_FuzzTest(const uint8_t* data, size_t size)
805    {
806        if (data == nullptr || size <= 0) {
807            std::cout << "illegal input!";
808            return;
809        }
810        RuntimeOption option;
811        option.SetLogLevel(RuntimeOption::LOG_LEVEL::ERROR);
812        EcmaVM *vm = JSNApi::CreateJSVM(option);
813        {
814            JsiFastNativeScope scope(vm);
815            auto thread = vm->GetAssociatedJSThread();
816            auto factory = vm->GetFactory();
817
818            uint32_t inputNum = 0;
819            std::string inputStr(data, data + size);
820            const uint32_t MAXBYTELEN = 4;
821            if (size > MAXBYTELEN) {
822                size = MAXBYTELEN;
823            }
824            if (memcpy_s(&inputNum, MAXBYTELEN, data, size) != 0) {
825                std::cout << "memcpy_s failed!";
826                UNREACHABLE();
827            }
828            JSHandle<JSAPIPlainArray> plainArray = CreateJSAPIPlainArray(thread);
829            JSHandle<EcmaString> inputEcmaStr = factory->NewFromStdString(inputStr);
830            EcmaRuntimeCallInfo *callInfo = CreateEcmaRuntimeCallInfo(thread, 8); // 8 : means the argv length
831            callInfo->SetFunction(JSTaggedValue::Undefined());
832            callInfo->SetThis(plainArray.GetTaggedValue());
833            callInfo->SetCallArg(0, JSTaggedValue(static_cast<uint32_t>(inputNum)));
834            callInfo->SetCallArg(1, inputEcmaStr.GetTaggedValue());
835            ContainersPlainArray::Add(callInfo);
836
837            EcmaRuntimeCallInfo *cfForGetSize = CreateEcmaRuntimeCallInfo(thread, 4); // 4 : means the argv length
838            cfForGetSize->SetFunction(JSTaggedValue::Undefined());
839            cfForGetSize->SetThis(plainArray.GetTaggedValue());
840            ContainersPlainArray::GetSize(cfForGetSize); // expected to return the size
841        }
842        JSNApi::DestroyJSVM(vm);
843    }
844}
845
846// Fuzzer entry point.
847extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size)
848{
849    // Run your code on data.
850    OHOS::ContainersPlainArray_Constructor_FuzzTest(data, size);
851    OHOS::ContainersPlainArray_Add_Has_FuzzTest(data, size);
852    OHOS::ContainersPlainArray_Clone_FuzzTest(data, size);
853    OHOS::ContainersPlainArray_Clear_FuzzTest(data, size);
854    OHOS::ContainersPlainArray_Get_FuzzTest(data, size);
855    OHOS::ContainersPlainArray_GetIteratorObj_FuzzTest(data, size);
856    OHOS::ContainersPlainArray_ForEach_FuzzTest(data, size);
857    OHOS::ContainersPlainArray_ToString_FuzzTest(data, size);
858    OHOS::ContainersPlainArray_GetIndexOfKey_FuzzTest(data, size);
859    OHOS::ContainersPlainArray_GetIndexOfValue_FuzzTest(data, size);
860    OHOS::ContainersPlainArray_IsEmpty_FuzzTest(data, size);
861    OHOS::ContainersPlainArray_GetKeyAt_FuzzTest(data, size);
862    OHOS::ContainersPlainArray_Remove_FuzzTest(data, size);
863    OHOS::ContainersPlainArray_RemoveAt_FuzzTest(data, size);
864    OHOS::ContainersPlainArray_RemoveRangeFrom_FuzzTest(data, size);
865    OHOS::ContainersPlainArray_SetValueAt_FuzzTest(data, size);
866    OHOS::ContainersPlainArray_GetValueAt_FuzzTest(data, size);
867    OHOS::ContainersPlainArray_GetSize_FuzzTest(data, size);
868    return 0;
869}