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 #ifndef CONTAINERSTREEMAPCOMMON_FUZZER_H
17 #define CONTAINERSTREEMAPCOMMON_FUZZER_H
18 
19 #include "ecmascript/containers/containers_hashmap.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_handle.h"
25 #include "ecmascript/napi/include/jsnapi.h"
26 
27 namespace panda::ecmascript {
28 using namespace panda::ecmascript::containers;
29 class ContainersHashMapFuzzTestHelper {
30 public:
JSObjectCreate(JSThread *thread)31     static JSFunction *JSObjectCreate(JSThread *thread)
32     {
33         EcmaVM *ecmaVM = thread->GetEcmaVM();
34         JSHandle<GlobalEnv> globalEnv = ecmaVM->GetGlobalEnv();
35         return globalEnv->GetObjectFunction().GetObject<JSFunction>();
36     }
37 
CreateEcmaRuntimeCallInfo(JSThread *thread, uint32_t numArgs)38     static EcmaRuntimeCallInfo *CreateEcmaRuntimeCallInfo(JSThread *thread, uint32_t numArgs)
39     {
40         auto factory = thread->GetEcmaVM()->GetFactory();
41         JSHandle<JSTaggedValue> hclass(thread, JSObjectCreate(thread));
42         JSHandle<JSTaggedValue> callee(
43             factory->NewJSObjectByConstructor(JSHandle<JSFunction>::Cast(hclass), hclass));
44         JSHandle<JSTaggedValue> undefined = thread->GlobalConstants()->GetHandledUndefined();
45         EcmaRuntimeCallInfo *objCallInfo =
46             EcmaInterpreter::NewRuntimeCallInfo(thread, undefined, callee, undefined, numArgs);
47         return objCallInfo;
48     }
49 
InitializeHashMapConstructor(JSThread *thread)50     static JSTaggedValue InitializeHashMapConstructor(JSThread *thread)
51     {
52         ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
53         JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
54 
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);
61         objCallInfo->SetFunction(JSTaggedValue::Undefined());
62         objCallInfo->SetThis(value.GetTaggedValue());
63         objCallInfo->SetCallArg(0, JSTaggedValue(static_cast<int>(ContainerTag::HashMap)));
64         JSTaggedValue result = ContainersPrivate::Load(objCallInfo);
65         return result;
66     }
67 
CreateJSAPIHashMap(JSThread *thread)68     static JSHandle<JSAPIHashMap> CreateJSAPIHashMap(JSThread *thread)
69     {
70         JSHandle<JSFunction> newTarget(thread, InitializeHashMapConstructor(thread));
71         auto objCallInfo = CreateEcmaRuntimeCallInfo(thread, 4);
72         objCallInfo->SetFunction(newTarget.GetTaggedValue());
73         objCallInfo->SetNewTarget(newTarget.GetTaggedValue());
74         objCallInfo->SetThis(JSTaggedValue::Undefined());
75 
76         JSTaggedValue result = ContainersHashMap::HashMapConstructor(objCallInfo);
77         JSHandle<JSAPIHashMap> map(thread, result);
78         return map;
79     }
80 
InitializeFuzzTest(const uint8_t *data, size_t size, double &input, EcmaVM *&vm, JSThread *&thread)81     static bool InitializeFuzzTest(const uint8_t *data, size_t size, double &input, EcmaVM *&vm,
82                                    JSThread *&thread)
83     {
84         RuntimeOption option;
85         option.SetLogLevel(RuntimeOption::LOG_LEVEL::ERROR);
86         vm = JSNApi::CreateJSVM(option);
87         thread = vm->GetAssociatedJSThread();
88         if (vm == nullptr || thread == nullptr) {
89             return false;
90         }
91         if (size == 0) {
92             JSNApi::DestroyJSVM(vm);
93             return false;
94         }
95 
96         size_t maxByteLen = sizeof(uint32_t);
97         if (size > maxByteLen) {
98             size = maxByteLen;
99         }
100         if (memcpy_s(&input, maxByteLen, data, size) != 0) {
101             std::cout << "memcpy_s failed!";
102             UNREACHABLE();
103         }
104         return true;
105     }
106 
ContainersHashMapEntriesFuzzTest(const uint8_t *data, size_t size)107     static void ContainersHashMapEntriesFuzzTest(const uint8_t *data, size_t size)
108     {
109         EcmaVM *vm = nullptr;
110         JSThread *thread = nullptr;
111         double input = 0;
112         if (!InitializeFuzzTest(data, size, input, vm, thread)) {
113             return;
114         }
115 
116         JSHandle<JSAPIHashMap> tMap = CreateJSAPIHashMap(thread);
117         auto callInfo = CreateEcmaRuntimeCallInfo(thread, 8);
118         callInfo->SetFunction(JSTaggedValue::Undefined());
119         callInfo->SetThis(tMap.GetTaggedValue());
120         callInfo->SetCallArg(0, JSTaggedValue(input));
121         callInfo->SetCallArg(1, JSTaggedValue(input));
122         ContainersHashMap::Set(callInfo);
123 
124         auto callInfo2 = CreateEcmaRuntimeCallInfo(thread, 4);
125         callInfo2->SetFunction(JSTaggedValue::Undefined());
126         callInfo2->SetThis(tMap.GetTaggedValue());
127         ContainersHashMap::Entries(callInfo2);
128         JSNApi::DestroyJSVM(vm);
129     }
130 
ContainersHashMapFuzzTest(const uint8_t *data, size_t size)131     static void ContainersHashMapFuzzTest(const uint8_t *data, size_t size)
132     {
133         EcmaVM *vm = nullptr;
134         JSThread *thread = nullptr;
135         double input = 0;
136         if (!InitializeFuzzTest(data, size, input, vm, thread)) {
137             return;
138         }
139         JSHandle<JSAPIHashMap> stack = CreateJSAPIHashMap(thread);
140         EcmaRuntimeCallInfo *callInfo = CreateEcmaRuntimeCallInfo(thread, 6);
141         callInfo->SetFunction(JSTaggedValue::Undefined());
142         callInfo->SetThis(stack.GetTaggedValue());
143         callInfo->SetCallArg(0, JSTaggedValue(input));
144         ContainersHashMap::HashMapConstructor(callInfo);
145         JSNApi::DestroyJSVM(vm);
146     }
147 
ContainersHashMapClearFuzzTest(const uint8_t *data, size_t size)148     static void ContainersHashMapClearFuzzTest(const uint8_t *data, size_t size)
149     {
150         EcmaVM *vm = nullptr;
151         JSThread *thread = nullptr;
152         double input = 0;
153         if (!InitializeFuzzTest(data, size, input, vm, thread)) {
154             return;
155         }
156 
157         JSHandle<JSAPIHashMap> tMap = CreateJSAPIHashMap(thread);
158         auto callInfo = CreateEcmaRuntimeCallInfo(thread, 8);
159         callInfo->SetFunction(JSTaggedValue::Undefined());
160         callInfo->SetThis(tMap.GetTaggedValue());
161         callInfo->SetCallArg(0, JSTaggedValue(input));
162         callInfo->SetCallArg(1, JSTaggedValue(input));
163         ContainersHashMap::Set(callInfo);
164         auto callInfo1 = CreateEcmaRuntimeCallInfo(thread, 4);
165         callInfo1->SetFunction(JSTaggedValue::Undefined());
166         callInfo1->SetThis(tMap.GetTaggedValue());
167         ContainersHashMap::Clear(callInfo1);
168         JSNApi::DestroyJSVM(vm);
169     }
170 
ContainersHashMapForEachFuzzTest(const uint8_t *data, size_t size)171     static void ContainersHashMapForEachFuzzTest(const uint8_t *data, size_t size)
172     {
173         EcmaVM *vm = nullptr;
174         JSThread *thread = nullptr;
175         double input = 0;
176         if (!InitializeFuzzTest(data, size, input, vm, thread)) {
177             return;
178         }
179 
180         JSHandle<JSAPIHashMap> tMap = CreateJSAPIHashMap(thread);
181         auto callInfo = CreateEcmaRuntimeCallInfo(thread, 8);
182         callInfo->SetFunction(JSTaggedValue::Undefined());
183         callInfo->SetThis(tMap.GetTaggedValue());
184         callInfo->SetCallArg(0, JSTaggedValue(input));
185         callInfo->SetCallArg(1, JSTaggedValue(input));
186         ContainersHashMap::Set(callInfo);
187         JSHandle<JSAPIHashMap> dMap = CreateJSAPIHashMap(thread);
188         auto callInfo1 = CreateEcmaRuntimeCallInfo(thread, 8);
189         callInfo1->SetFunction(JSTaggedValue::Undefined());
190         callInfo1->SetThis(tMap.GetTaggedValue());
191         callInfo1->SetCallArg(0, JSTaggedValue::Undefined());
192         callInfo1->SetCallArg(1, dMap.GetTaggedValue());
193         ContainersHashMap::ForEach(callInfo1);
194         JSNApi::DestroyJSVM(vm);
195     }
196 
ContainersHashMapGetFuzzTest(const uint8_t *data, size_t size)197     static void ContainersHashMapGetFuzzTest(const uint8_t *data, size_t size)
198     {
199         EcmaVM *vm = nullptr;
200         JSThread *thread = nullptr;
201         double input = 0;
202         if (!InitializeFuzzTest(data, size, input, vm, thread)) {
203             return;
204         }
205 
206         JSHandle<JSAPIHashMap> tMap = CreateJSAPIHashMap(thread);
207         auto callInfo = CreateEcmaRuntimeCallInfo(thread, 8);
208         callInfo->SetFunction(JSTaggedValue::Undefined());
209         callInfo->SetThis(tMap.GetTaggedValue());
210         callInfo->SetCallArg(0, JSTaggedValue(input));
211         callInfo->SetCallArg(1, JSTaggedValue(input + 1));
212         ContainersHashMap::Set(callInfo);
213 
214         auto callInfo1 = CreateEcmaRuntimeCallInfo(thread, 6);
215         callInfo1->SetFunction(JSTaggedValue::Undefined());
216         callInfo1->SetThis(tMap.GetTaggedValue());
217         callInfo1->SetCallArg(0, JSTaggedValue(input));
218         ContainersHashMap::Get(callInfo1);
219         JSNApi::DestroyJSVM(vm);
220     }
221 
ContainersHashMapGetLengthFuzzTest(const uint8_t *data, size_t size)222     static void ContainersHashMapGetLengthFuzzTest(const uint8_t *data, size_t size)
223     {
224         EcmaVM *vm = nullptr;
225         JSThread *thread = nullptr;
226         double input = 0;
227         if (!InitializeFuzzTest(data, size, input, vm, thread)) {
228             return;
229         }
230 
231         JSHandle<JSAPIHashMap> tMap = CreateJSAPIHashMap(thread);
232         auto callInfo = CreateEcmaRuntimeCallInfo(thread, 8);
233         callInfo->SetFunction(JSTaggedValue::Undefined());
234         callInfo->SetThis(tMap.GetTaggedValue());
235         callInfo->SetCallArg(0, JSTaggedValue(input));
236         callInfo->SetCallArg(1, JSTaggedValue(input));
237         ContainersHashMap::Set(callInfo);
238 
239         auto callInfo1 = CreateEcmaRuntimeCallInfo(thread, 4);
240         callInfo1->SetFunction(JSTaggedValue::Undefined());
241         callInfo1->SetThis(tMap.GetTaggedValue());
242         ContainersHashMap::GetLength(callInfo1);
243         JSNApi::DestroyJSVM(vm);
244     }
245 
ContainersHashMapHasKeyFuzzTest(const uint8_t *data, size_t size)246     static void ContainersHashMapHasKeyFuzzTest(const uint8_t *data, size_t size)
247     {
248         EcmaVM *vm = nullptr;
249         JSThread *thread = nullptr;
250         double input = 0;
251         if (!InitializeFuzzTest(data, size, input, vm, thread)) {
252             return;
253         }
254 
255         JSHandle<JSAPIHashMap> tMap = CreateJSAPIHashMap(thread);
256         auto callInfo = CreateEcmaRuntimeCallInfo(thread, 8);
257         callInfo->SetFunction(JSTaggedValue::Undefined());
258         callInfo->SetThis(tMap.GetTaggedValue());
259         callInfo->SetCallArg(0, JSTaggedValue(input));
260         callInfo->SetCallArg(1, JSTaggedValue(input));
261         ContainersHashMap::Set(callInfo);
262 
263         EcmaRuntimeCallInfo *callInfo1 = CreateEcmaRuntimeCallInfo(thread, 6);
264         callInfo1->SetFunction(JSTaggedValue::Undefined());
265         callInfo1->SetThis(tMap.GetTaggedValue());
266         callInfo1->SetCallArg(0, JSTaggedValue(input));
267         ContainersHashMap::HasKey(callInfo1);
268         JSNApi::DestroyJSVM(vm);
269     }
270 
ContainersHashMapHasValueFuzzTest(const uint8_t *data, size_t size)271     static void ContainersHashMapHasValueFuzzTest(const uint8_t *data, size_t size)
272     {
273         EcmaVM *vm = nullptr;
274         JSThread *thread = nullptr;
275         double input = 0;
276         if (!InitializeFuzzTest(data, size, input, vm, thread)) {
277             return;
278         }
279 
280         JSHandle<JSAPIHashMap> tMap = CreateJSAPIHashMap(thread);
281         auto callInfo = CreateEcmaRuntimeCallInfo(thread, 8);
282         callInfo->SetFunction(JSTaggedValue::Undefined());
283         callInfo->SetThis(tMap.GetTaggedValue());
284         callInfo->SetCallArg(0, JSTaggedValue(input));
285         callInfo->SetCallArg(1, JSTaggedValue(input));
286         ContainersHashMap::Set(callInfo);
287 
288         EcmaRuntimeCallInfo *callInfo1 = CreateEcmaRuntimeCallInfo(thread, 6);
289         callInfo1->SetFunction(JSTaggedValue::Undefined());
290         callInfo1->SetThis(tMap.GetTaggedValue());
291         callInfo1->SetCallArg(0, JSTaggedValue(input));
292         ContainersHashMap::HasValue(callInfo1);
293         JSNApi::DestroyJSVM(vm);
294     }
295 
ContainersHashMapIsEmptyFuzzTest(const uint8_t *data, size_t size)296     static void ContainersHashMapIsEmptyFuzzTest(const uint8_t *data, size_t size)
297     {
298         EcmaVM *vm = nullptr;
299         JSThread *thread = nullptr;
300         double input = 0;
301         if (!InitializeFuzzTest(data, size, input, vm, thread)) {
302             return;
303         }
304 
305         JSHandle<JSAPIHashMap> tMap = CreateJSAPIHashMap(thread);
306         auto callInfo = CreateEcmaRuntimeCallInfo(thread, 8);
307         callInfo->SetFunction(JSTaggedValue::Undefined());
308         callInfo->SetThis(tMap.GetTaggedValue());
309         callInfo->SetCallArg(0, JSTaggedValue(input));
310         callInfo->SetCallArg(1, JSTaggedValue(input));
311         ContainersHashMap::Set(callInfo);
312         EcmaRuntimeCallInfo *callInfo2 = CreateEcmaRuntimeCallInfo(thread, 4);
313         callInfo2->SetFunction(JSTaggedValue::Undefined());
314         callInfo2->SetThis(tMap.GetTaggedValue());
315         ContainersHashMap::IsEmpty(callInfo2);
316         JSNApi::DestroyJSVM(vm);
317     }
318 
ContainersHashMapKeysFuzzTest(const uint8_t *data, size_t size)319     static void ContainersHashMapKeysFuzzTest(const uint8_t *data, size_t size)
320     {
321         EcmaVM *vm = nullptr;
322         JSThread *thread = nullptr;
323         double input = 0;
324         if (!InitializeFuzzTest(data, size, input, vm, thread)) {
325             return;
326         }
327 
328         JSHandle<JSAPIHashMap> tMap = CreateJSAPIHashMap(thread);
329         auto callInfo = CreateEcmaRuntimeCallInfo(thread, 8);
330         callInfo->SetFunction(JSTaggedValue::Undefined());
331         callInfo->SetThis(tMap.GetTaggedValue());
332         callInfo->SetCallArg(0, JSTaggedValue(input));
333         callInfo->SetCallArg(1, JSTaggedValue(input));
334         ContainersHashMap::Set(callInfo);
335 
336         auto callInfo1 = CreateEcmaRuntimeCallInfo(thread, 4);
337         callInfo1->SetFunction(JSTaggedValue::Undefined());
338         callInfo1->SetThis(tMap.GetTaggedValue());
339         ContainersHashMap::Keys(callInfo1);
340         JSNApi::DestroyJSVM(vm);
341     }
342 
ContainersHashMapRemoveFuzzTest(const uint8_t *data, size_t size)343     static void ContainersHashMapRemoveFuzzTest(const uint8_t *data, size_t size)
344     {
345         EcmaVM *vm = nullptr;
346         JSThread *thread = nullptr;
347         double input = 0;
348         if (!InitializeFuzzTest(data, size, input, vm, thread)) {
349             return;
350         }
351 
352         JSHandle<JSAPIHashMap> tMap = CreateJSAPIHashMap(thread);
353         auto callInfo = CreateEcmaRuntimeCallInfo(thread, 8);
354         callInfo->SetFunction(JSTaggedValue::Undefined());
355         callInfo->SetThis(tMap.GetTaggedValue());
356         callInfo->SetCallArg(0, JSTaggedValue(input));
357         callInfo->SetCallArg(1, JSTaggedValue(input));
358         ContainersHashMap::Set(callInfo);
359 
360         auto callInfo1 = CreateEcmaRuntimeCallInfo(thread, 6);
361         callInfo1->SetFunction(JSTaggedValue::Undefined());
362         callInfo1->SetThis(tMap.GetTaggedValue());
363         callInfo1->SetCallArg(0, JSTaggedValue(input + 1));
364         ContainersHashMap::Remove(callInfo1);
365         JSNApi::DestroyJSVM(vm);
366     }
367 
ContainersHashMapReplaceFuzzTest(const uint8_t *data, size_t size)368     static void ContainersHashMapReplaceFuzzTest(const uint8_t *data, size_t size)
369     {
370         EcmaVM *vm = nullptr;
371         JSThread *thread = nullptr;
372         double input = 0;
373         if (!InitializeFuzzTest(data, size, input, vm, thread)) {
374             return;
375         }
376 
377         JSHandle<JSAPIHashMap> tMap = CreateJSAPIHashMap(thread);
378         auto callInfo = CreateEcmaRuntimeCallInfo(thread, 8);
379         callInfo->SetFunction(JSTaggedValue::Undefined());
380         callInfo->SetThis(tMap.GetTaggedValue());
381         callInfo->SetCallArg(0, JSTaggedValue(input));
382         callInfo->SetCallArg(1, JSTaggedValue(input));
383         ContainersHashMap::Set(callInfo);
384 
385         EcmaRuntimeCallInfo *callInfo1 = CreateEcmaRuntimeCallInfo(thread, 8);
386         callInfo1->SetFunction(JSTaggedValue::Undefined());
387         callInfo1->SetThis(tMap.GetTaggedValue());
388         callInfo1->SetCallArg(0, JSTaggedValue(input + 1));
389         callInfo1->SetCallArg(1, JSTaggedValue(input));
390         ContainersHashMap::Replace(callInfo1);
391         JSNApi::DestroyJSVM(vm);
392     }
393 
ContainersHashMapSetFuzzTest(const uint8_t *data, size_t size)394     static void ContainersHashMapSetFuzzTest(const uint8_t *data, size_t size)
395     {
396         EcmaVM *vm = nullptr;
397         JSThread *thread = nullptr;
398         double input = 0;
399         if (!InitializeFuzzTest(data, size, input, vm, thread)) {
400             return;
401         }
402 
403         JSHandle<JSAPIHashMap> tMap = CreateJSAPIHashMap(thread);
404         auto callInfo = CreateEcmaRuntimeCallInfo(thread, 8);
405         callInfo->SetFunction(JSTaggedValue::Undefined());
406         callInfo->SetThis(tMap.GetTaggedValue());
407         callInfo->SetCallArg(0, JSTaggedValue(input));
408         callInfo->SetCallArg(1, JSTaggedValue(input + 1));
409         ContainersHashMap::Set(callInfo);
410         JSNApi::DestroyJSVM(vm);
411     }
412 
ContainersHashMapSetAllFuzzTest(const uint8_t *data, size_t size)413     static void ContainersHashMapSetAllFuzzTest(const uint8_t *data, size_t size)
414     {
415         EcmaVM *vm = nullptr;
416         JSThread *thread = nullptr;
417         double input = 0;
418         if (!InitializeFuzzTest(data, size, input, vm, thread)) {
419             return;
420         }
421 
422         JSHandle<JSAPIHashMap> tMap = CreateJSAPIHashMap(thread);
423         auto callInfo = CreateEcmaRuntimeCallInfo(thread, 8);
424         callInfo->SetFunction(JSTaggedValue::Undefined());
425         callInfo->SetThis(tMap.GetTaggedValue());
426         callInfo->SetCallArg(0, JSTaggedValue(input));
427         callInfo->SetCallArg(1, JSTaggedValue(input));
428         ContainersHashMap::Set(callInfo);
429 
430         JSHandle<JSAPIHashMap> dMap = CreateJSAPIHashMap(thread);
431         auto callInfo1 = CreateEcmaRuntimeCallInfo(thread, 6);
432         callInfo1->SetFunction(JSTaggedValue::Undefined());
433         callInfo1->SetThis(dMap.GetTaggedValue());
434         callInfo1->SetCallArg(0, tMap.GetTaggedValue());
435         ContainersHashMap::SetAll(callInfo1);
436         JSNApi::DestroyJSVM(vm);
437     }
438 
ContainersHashMapValuesFuzzTest(const uint8_t *data, size_t size)439     static void ContainersHashMapValuesFuzzTest(const uint8_t *data, size_t size)
440     {
441         EcmaVM *vm = nullptr;
442         JSThread *thread = nullptr;
443         double input = 0;
444         if (!InitializeFuzzTest(data, size, input, vm, thread)) {
445             return;
446         }
447 
448         JSHandle<JSAPIHashMap> tMap = CreateJSAPIHashMap(thread);
449         auto callInfo = CreateEcmaRuntimeCallInfo(thread, 8);
450         callInfo->SetFunction(JSTaggedValue::Undefined());
451         callInfo->SetThis(tMap.GetTaggedValue());
452         callInfo->SetCallArg(0, JSTaggedValue(input));
453         callInfo->SetCallArg(1, JSTaggedValue(input));
454         ContainersHashMap::Set(callInfo);
455 
456         auto callInfo1 = CreateEcmaRuntimeCallInfo(thread, 4);
457         callInfo1->SetFunction(JSTaggedValue::Undefined());
458         callInfo1->SetThis(tMap.GetTaggedValue());
459         ContainersHashMap::Values(callInfo1);
460         JSNApi::DestroyJSVM(vm);
461     }
462 };
463 }  // namespace panda::ecmascript
464 #endif