• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #ifndef CONTAINERSDEQUECOMMON_FUZZER_H
17 #define CONTAINERSDEQUECOMMON_FUZZER_H
18 
19 #include "ecmascript/containers/containers_deque.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_deque.h"
25 #include "ecmascript/js_api/js_api_deque_iterator.h"
26 #include "ecmascript/js_handle.h"
27 #include "ecmascript/js_tagged_value-inl.h"
28 #include "ecmascript/napi/include/jsnapi.h"
29 #include "ecmascript/ecma_runtime_call_info.h"
30 #include "ecmascript/js_thread.h"
31 #include "ecmascript/object_factory.h"
32 
33 #define MAXBYTELEN sizeof(unsigned int)
34 
35 namespace panda::ecmascript {
36 using namespace panda::ecmascript::containers;
37 class ContainersDequeFuzzTestHelper {
38 public:
JSObjectCreate(JSThread * thread)39     static JSFunction *JSObjectCreate(JSThread *thread)
40     {
41         EcmaVM *ecmaVM = thread->GetEcmaVM();
42         JSHandle<GlobalEnv> globalEnv = ecmaVM->GetGlobalEnv();
43         return globalEnv->GetObjectFunction().GetObject<JSFunction>();
44     }
45 
CreateEcmaRuntimeCallInfo(JSThread * thread,uint32_t numArgs)46     static EcmaRuntimeCallInfo *CreateEcmaRuntimeCallInfo(JSThread *thread, uint32_t numArgs)
47     {
48         auto factory = thread->GetEcmaVM()->GetFactory();
49         JSHandle<JSTaggedValue> hclass(thread, JSObjectCreate(thread));
50         JSHandle<JSTaggedValue> callee(factory->NewJSObjectByConstructor(JSHandle<JSFunction>::Cast(hclass), hclass));
51         JSHandle<JSTaggedValue> undefined = thread->GlobalConstants()->GetHandledUndefined();
52         EcmaRuntimeCallInfo *objCallInfo =
53             EcmaInterpreter::NewRuntimeCallInfo(thread, undefined, callee, undefined, numArgs);
54         return objCallInfo;
55     }
56 
CreateJSAPIDeque(JSThread * thread)57     static JSHandle<JSAPIDeque> CreateJSAPIDeque(JSThread *thread)
58     {
59         auto factory = thread->GetEcmaVM()->GetFactory();
60         JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
61         JSHandle<JSTaggedValue> globalObject = env->GetJSGlobalObject();
62         JSHandle<JSTaggedValue> key(factory->NewFromASCII("ArkPrivate"));
63         JSHandle<JSTaggedValue> value =
64             JSObject::GetProperty(thread, JSHandle<JSTaggedValue>(globalObject), key).GetValue();
65 
66         auto objCallInfo = CreateEcmaRuntimeCallInfo(thread, 6); // 6 : means the argv length
67         objCallInfo->SetFunction(JSTaggedValue::Undefined());
68         objCallInfo->SetThis(value.GetTaggedValue());
69         objCallInfo->SetCallArg(0, JSTaggedValue(static_cast<int>(ContainerTag::Deque))); // 0 means the argument
70         JSTaggedValue result = ContainersPrivate::Load(objCallInfo);
71 
72         JSHandle<JSFunction> newTarget(thread, result);
73         auto objCallInfo2 = CreateEcmaRuntimeCallInfo(thread, 6); // 6 : means the argv length
74         objCallInfo2->SetFunction(newTarget.GetTaggedValue());
75         objCallInfo2->SetNewTarget(newTarget.GetTaggedValue());
76         objCallInfo2->SetThis(JSTaggedValue::Undefined());
77         objCallInfo2->SetCallArg(0, JSTaggedValue::Undefined());
78 
79         JSTaggedValue list = ContainersDeque::DequeConstructor(objCallInfo2);
80         JSHandle<JSAPIDeque> deque(thread, list);
81         return deque;
82     }
83 
ContainersDequeInsertFrontFuzzTest(const uint8_t * data,size_t size)84     static void ContainersDequeInsertFrontFuzzTest(const uint8_t* data, size_t size)
85     {
86         RuntimeOption option;
87         option.SetLogLevel(RuntimeOption::LOG_LEVEL::ERROR);
88         EcmaVM *vm = JSNApi::CreateJSVM(option);
89         auto thread = vm->GetAssociatedJSThread();
90         JSHandle<JSAPIDeque> deque = CreateJSAPIDeque(thread);
91 
92         auto callInfo = CreateEcmaRuntimeCallInfo(thread, 6);
93         callInfo->SetFunction(JSTaggedValue::Undefined());
94         callInfo->SetThis(deque.GetTaggedValue());
95         ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
96         std::string str(data, data + size);
97         JSTaggedValue value = factory->NewFromStdString(str).GetTaggedValue();
98         callInfo->SetCallArg(0, value);
99 
100         ContainersDeque::InsertFront(callInfo);
101 
102         JSNApi::DestroyJSVM(vm);
103     }
104 
105     class TestClass : public base::BuiltinsBase {
106         public:
TestForEachFunc(EcmaRuntimeCallInfo * argv)107             static JSTaggedValue TestForEachFunc(EcmaRuntimeCallInfo *argv)
108             {
109                 JSThread *thread = argv->GetThread();
110                 JSHandle<JSTaggedValue> value = GetCallArg(argv, 0);
111                 JSHandle<JSTaggedValue> index = GetCallArg(argv, 1);
112                 JSHandle<JSTaggedValue> deque = GetCallArg(argv, 2); // 2 means the secode arg
113                 if (!deque->IsUndefined()) {
114                     if (index->IsNumber() && value->IsNumber()) {
115                         // 2 means mul by 2
116                         JSHandle<JSAPIDeque>::Cast(deque)->Set(thread, index->GetInt(), JSTaggedValue(value->GetInt() * 2));
117                     }
118                 }
119                 return JSTaggedValue::True();
120             }
121     };
122 
ContainersDequeForEachFuzzTest(const uint8_t * data,size_t size)123     static void ContainersDequeForEachFuzzTest(const uint8_t* data, size_t size)
124     {
125         uint32_t input = 0;
126         if (size <= 0) {
127             return;
128         }
129         if (size > MAXBYTELEN) {
130             size = MAXBYTELEN;
131         }
132         if (memcpy_s(&input, MAXBYTELEN, data, size) != 0) {
133             std::cout << "memcpy_s failed!";
134             UNREACHABLE();
135         }
136 
137         RuntimeOption option;
138         option.SetLogLevel(RuntimeOption::LOG_LEVEL::ERROR);
139         EcmaVM *vm = JSNApi::CreateJSVM(option);
140         auto thread = vm->GetAssociatedJSThread();
141 
142         constexpr uint32_t NODE_NUMBERS = 8;
143         JSHandle<JSAPIDeque> deque = CreateJSAPIDeque(thread);
144         for (uint32_t i = 0; i < NODE_NUMBERS; i++) {
145             auto callInfo = CreateEcmaRuntimeCallInfo(thread, 8);
146             callInfo->SetFunction(JSTaggedValue::Undefined());
147             callInfo->SetThis(deque.GetTaggedValue());
148             callInfo->SetCallArg(0, JSTaggedValue(i + input));
149             ContainersDeque::InsertFront(callInfo);
150         }
151 
152         JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
153         JSHandle<JSFunction> func = thread->GetEcmaVM()->GetFactory()->NewJSFunction(env,
154                                     reinterpret_cast<void *>(TestClass::TestForEachFunc));
155         auto callInfo = CreateEcmaRuntimeCallInfo(thread, 8);
156         callInfo->SetFunction(JSTaggedValue::Undefined());
157         callInfo->SetThis(deque.GetTaggedValue());
158         callInfo->SetCallArg(0, func.GetTaggedValue());
159         callInfo->SetCallArg(1, deque.GetTaggedValue());
160 
161         ContainersDeque::ForEach(callInfo);
162 
163         JSNApi::DestroyJSVM(vm);
164     }
165 
ContainersDequeGetFirstFuzzTest(const uint8_t * data,size_t size)166     static void ContainersDequeGetFirstFuzzTest(const uint8_t* data, size_t size)
167     {
168         RuntimeOption option;
169         option.SetLogLevel(RuntimeOption::LOG_LEVEL::ERROR);
170         EcmaVM *vm = JSNApi::CreateJSVM(option);
171         auto thread = vm->GetAssociatedJSThread();
172 
173         JSHandle<JSAPIDeque> deque = CreateJSAPIDeque(thread);
174         auto callInfo = CreateEcmaRuntimeCallInfo(thread, 8);
175         callInfo->SetFunction(JSTaggedValue::Undefined());
176         callInfo->SetThis(deque.GetTaggedValue());
177 
178         unsigned int input = 0;
179         if (size <= 0) {
180             return;
181         }
182         if (size > MAXBYTELEN) {
183             size = MAXBYTELEN;
184         }
185         if (memcpy_s(&input, MAXBYTELEN, data, size) != 0) {
186             std::cout << "memcpy_s failed!";
187             UNREACHABLE();
188         }
189         callInfo->SetCallArg(0, JSTaggedValue(input));
190 
191         ContainersDeque::InsertFront(callInfo);
192 
193         auto callInfo1 = CreateEcmaRuntimeCallInfo(thread, 4);
194         callInfo1->SetFunction(JSTaggedValue::Undefined());
195         callInfo1->SetThis(deque.GetTaggedValue());
196         ContainersDeque::GetFirst(callInfo1);
197 
198         JSNApi::DestroyJSVM(vm);
199         return;
200     }
201 
ContainersDequeGetLastFuzzTest(const uint8_t * data,size_t size)202     static void ContainersDequeGetLastFuzzTest(const uint8_t* data, size_t size)
203     {
204         RuntimeOption option;
205         option.SetLogLevel(RuntimeOption::LOG_LEVEL::ERROR);
206         EcmaVM *vm = JSNApi::CreateJSVM(option);
207         auto thread = vm->GetAssociatedJSThread();
208 
209         JSHandle<JSAPIDeque> deque = CreateJSAPIDeque(thread);
210         auto callInfo = CreateEcmaRuntimeCallInfo(thread, 8);
211         callInfo->SetFunction(JSTaggedValue::Undefined());
212         callInfo->SetThis(deque.GetTaggedValue());
213 
214         unsigned int input = 0;
215         if (size <= 0) {
216             return;
217         }
218         if (size > MAXBYTELEN) {
219             size = MAXBYTELEN;
220         }
221         if (memcpy_s(&input, MAXBYTELEN, data, size) != 0) {
222             std::cout << "memcpy_s failed!";
223             UNREACHABLE();
224         }
225         callInfo->SetCallArg(0, JSTaggedValue(input));
226 
227         ContainersDeque::InsertFront(callInfo);
228 
229         auto callInfo1 = CreateEcmaRuntimeCallInfo(thread, 4);
230         callInfo1->SetFunction(JSTaggedValue::Undefined());
231         callInfo1->SetThis(deque.GetTaggedValue());
232         ContainersDeque::GetLast(callInfo1);
233 
234         JSNApi::DestroyJSVM(vm);
235         return;
236     }
237 
ContainersDequeInsertEndFuzzTest(const uint8_t * data,size_t size)238     static void ContainersDequeInsertEndFuzzTest(const uint8_t* data, size_t size)
239     {
240         RuntimeOption option;
241         option.SetLogLevel(RuntimeOption::LOG_LEVEL::ERROR);
242         EcmaVM *vm = JSNApi::CreateJSVM(option);
243         auto thread = vm->GetAssociatedJSThread();
244 
245         JSHandle<JSAPIDeque> deque = CreateJSAPIDeque(thread);
246         auto callInfo = CreateEcmaRuntimeCallInfo(thread, 8);
247         callInfo->SetFunction(JSTaggedValue::Undefined());
248         callInfo->SetThis(deque.GetTaggedValue());
249 
250         unsigned int input = 0;
251         if (size <= 0) {
252             return;
253         }
254         if (size > MAXBYTELEN) {
255             size = MAXBYTELEN;
256         }
257         if (memcpy_s(&input, MAXBYTELEN, data, size) != 0) {
258             std::cout << "memcpy_s failed!";
259             UNREACHABLE();
260         }
261         callInfo->SetCallArg(0, JSTaggedValue(input));
262 
263         ContainersDeque::InsertEnd(callInfo);
264 
265         JSNApi::DestroyJSVM(vm);
266         return;
267     }
268 
ContainersDequeHasFuzzTest(const uint8_t * data,size_t size)269     static void ContainersDequeHasFuzzTest(const uint8_t* data, size_t size)
270     {
271         RuntimeOption option;
272         option.SetLogLevel(RuntimeOption::LOG_LEVEL::ERROR);
273         EcmaVM *vm = JSNApi::CreateJSVM(option);
274         auto thread = vm->GetAssociatedJSThread();
275 
276         JSHandle<JSAPIDeque> deque = CreateJSAPIDeque(thread);
277         auto callInfo = CreateEcmaRuntimeCallInfo(thread, 8);
278         callInfo->SetFunction(JSTaggedValue::Undefined());
279         callInfo->SetThis(deque.GetTaggedValue());
280 
281         unsigned int input = 0;
282         if (size <= 0) {
283             return;
284         }
285         if (size > MAXBYTELEN) {
286             size = MAXBYTELEN;
287         }
288         if (memcpy_s(&input, MAXBYTELEN, data, size) != 0) {
289             std::cout << "memcpy_s failed!";
290             UNREACHABLE();
291         }
292         callInfo->SetCallArg(0, JSTaggedValue(input));
293 
294         ContainersDeque::InsertEnd(callInfo);
295 
296         auto callInfo1 = CreateEcmaRuntimeCallInfo(thread, 8);
297         callInfo1->SetFunction(JSTaggedValue::Undefined());
298         callInfo1->SetThis(deque.GetTaggedValue());
299         callInfo1->SetCallArg(0, JSTaggedValue(input));
300 
301         ContainersDeque::Has(callInfo1);
302 
303         JSNApi::DestroyJSVM(vm);
304         return;
305     }
306 
ContainersDequePopFirstFuzzTest(const uint8_t * data,size_t size)307     static void ContainersDequePopFirstFuzzTest(const uint8_t* data, size_t size)
308     {
309         RuntimeOption option;
310         option.SetLogLevel(RuntimeOption::LOG_LEVEL::ERROR);
311         EcmaVM *vm = JSNApi::CreateJSVM(option);
312         auto thread = vm->GetAssociatedJSThread();
313 
314         JSHandle<JSAPIDeque> deque = CreateJSAPIDeque(thread);
315         auto callInfo = CreateEcmaRuntimeCallInfo(thread, 8);
316         callInfo->SetFunction(JSTaggedValue::Undefined());
317         callInfo->SetThis(deque.GetTaggedValue());
318 
319         unsigned int input = 0;
320         if (size <= 0) {
321             return;
322         }
323         if (size > MAXBYTELEN) {
324             size = MAXBYTELEN;
325         }
326         if (memcpy_s(&input, MAXBYTELEN, data, size) != 0) {
327             std::cout << "memcpy_s failed!";
328             UNREACHABLE();
329         }
330         callInfo->SetCallArg(0, JSTaggedValue(input));
331 
332         ContainersDeque::InsertFront(callInfo);
333 
334         auto callInfo1 = CreateEcmaRuntimeCallInfo(thread, 4);
335         callInfo1->SetFunction(JSTaggedValue::Undefined());
336         callInfo1->SetThis(deque.GetTaggedValue());
337         ContainersDeque::PopFirst(callInfo1);
338 
339         JSNApi::DestroyJSVM(vm);
340         return;
341     }
342 
ContainersDequePopLastFuzzTest(const uint8_t * data,size_t size)343     static void ContainersDequePopLastFuzzTest(const uint8_t* data, size_t size)
344     {
345         RuntimeOption option;
346         option.SetLogLevel(RuntimeOption::LOG_LEVEL::ERROR);
347         EcmaVM *vm = JSNApi::CreateJSVM(option);
348         auto thread = vm->GetAssociatedJSThread();
349 
350         JSHandle<JSAPIDeque> deque = CreateJSAPIDeque(thread);
351         auto callInfo = CreateEcmaRuntimeCallInfo(thread, 8);
352         callInfo->SetFunction(JSTaggedValue::Undefined());
353         callInfo->SetThis(deque.GetTaggedValue());
354 
355         unsigned int input = 0;
356         if (size <= 0) {
357             return;
358         }
359         if (size > MAXBYTELEN) {
360             size = MAXBYTELEN;
361         }
362         if (memcpy_s(&input, MAXBYTELEN, data, size) != 0) {
363             std::cout << "memcpy_s failed!";
364             UNREACHABLE();
365         }
366         callInfo->SetCallArg(0, JSTaggedValue(input));
367 
368         ContainersDeque::InsertFront(callInfo);
369 
370         auto callInfo1 = CreateEcmaRuntimeCallInfo(thread, 4);
371         callInfo1->SetFunction(JSTaggedValue::Undefined());
372         callInfo1->SetThis(deque.GetTaggedValue());
373         ContainersDeque::PopLast(callInfo1);
374 
375         JSNApi::DestroyJSVM(vm);
376         return;
377     }
378 
ContainersDequeIteratorFuzzTest(const uint8_t * data,size_t size)379     static void ContainersDequeIteratorFuzzTest(const uint8_t* data, size_t size)
380     {
381         RuntimeOption option;
382         option.SetLogLevel(RuntimeOption::LOG_LEVEL::ERROR);
383         EcmaVM *vm = JSNApi::CreateJSVM(option);
384         auto thread = vm->GetAssociatedJSThread();
385 
386         uint32_t input = 0;
387         if (size <= 0) {
388             return;
389         }
390         if (size > MAXBYTELEN) {
391             size = MAXBYTELEN;
392         }
393         if (memcpy_s(&input, MAXBYTELEN, data, size) != 0) {
394             std::cout << "memcpy_s failed!";
395             UNREACHABLE();
396         }
397 
398         constexpr uint32_t NODE_NUMBERS = 8;
399         JSHandle<JSAPIDeque> deque = CreateJSAPIDeque(thread);
400         for (uint32_t i = 0; i < NODE_NUMBERS; i++) {
401             auto callInfo = CreateEcmaRuntimeCallInfo(thread, 8);
402             callInfo->SetFunction(JSTaggedValue::Undefined());
403             callInfo->SetThis(deque.GetTaggedValue());
404             callInfo->SetCallArg(0, JSTaggedValue(i + input));
405 
406             ContainersDeque::InsertEnd(callInfo);
407         }
408 
409         auto callInfo1 = CreateEcmaRuntimeCallInfo(thread, 4);
410         callInfo1->SetFunction(JSTaggedValue::Undefined());
411         callInfo1->SetThis(deque.GetTaggedValue());
412         JSHandle<JSTaggedValue> iterValues(thread, ContainersDeque::GetIteratorObj(callInfo1));
413 
414         JSMutableHandle<JSTaggedValue> result(thread, JSTaggedValue::Undefined());
415         for (uint32_t i = 0; i < NODE_NUMBERS; i++) {
416             auto callInfo = CreateEcmaRuntimeCallInfo(thread, 4);
417             callInfo->SetFunction(JSTaggedValue::Undefined());
418             callInfo->SetThis(iterValues.GetTaggedValue());
419 
420             result.Update(JSAPIDequeIterator::Next(callInfo));
421         }
422 
423         JSNApi::DestroyJSVM(vm);
424         return;
425     }
426 
427 };
428 }
429 #endif