• 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(common::LOG_LEVEL::ERROR);
88         EcmaVM *vm = JSNApi::CreateJSVM(option);
89         {
90             JsiFastNativeScope scope(vm);
91             auto thread = vm->GetAssociatedJSThread();
92             JSHandle<JSAPIDeque> deque = CreateJSAPIDeque(thread);
93 
94             auto callInfo = CreateEcmaRuntimeCallInfo(thread, 6);
95             callInfo->SetFunction(JSTaggedValue::Undefined());
96             callInfo->SetThis(deque.GetTaggedValue());
97             ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
98             std::string str(data, data + size);
99             JSTaggedValue value = factory->NewFromStdString(str).GetTaggedValue();
100             callInfo->SetCallArg(0, value);
101             ContainersDeque::InsertFront(callInfo);
102         }
103         JSNApi::DestroyJSVM(vm);
104     }
105 
106     class TestClass : public base::BuiltinsBase {
107         public:
TestForEachFunc(EcmaRuntimeCallInfo * argv)108             static JSTaggedValue TestForEachFunc(EcmaRuntimeCallInfo *argv)
109             {
110                 JSThread *thread = argv->GetThread();
111                 JSHandle<JSTaggedValue> value = GetCallArg(argv, 0);
112                 JSHandle<JSTaggedValue> index = GetCallArg(argv, 1);
113                 JSHandle<JSTaggedValue> deque = GetCallArg(argv, 2); // 2 means the secode arg
114                 if (!deque->IsUndefined()) {
115                     if (index->IsNumber() && value->IsNumber()) {
116                         JSHandle<JSAPIDeque>::Cast(deque)->Set(thread, index->GetInt(),
117                             JSTaggedValue(value->GetInt() * 2));    // 2 means mul by 2
118                     }
119                 }
120                 return JSTaggedValue::True();
121             }
122     };
123 
ContainersDequeGetFirstFuzzTest(const uint8_t * data,size_t size)124     static void ContainersDequeGetFirstFuzzTest(const uint8_t* data, size_t size)
125     {
126         RuntimeOption option;
127         option.SetLogLevel(common::LOG_LEVEL::ERROR);
128         EcmaVM *vm = JSNApi::CreateJSVM(option);
129         {
130             JsiFastNativeScope scope(vm);
131             auto thread = vm->GetAssociatedJSThread();
132 
133             JSHandle<JSAPIDeque> deque = CreateJSAPIDeque(thread);
134             auto callInfo = CreateEcmaRuntimeCallInfo(thread, 8);
135             callInfo->SetFunction(JSTaggedValue::Undefined());
136             callInfo->SetThis(deque.GetTaggedValue());
137 
138             unsigned int input = 0;
139             if (size <= 0) {
140                 return;
141             }
142             if (size > MAXBYTELEN) {
143                 size = MAXBYTELEN;
144             }
145             if (memcpy_s(&input, MAXBYTELEN, data, size) != 0) {
146                 std::cout << "memcpy_s failed!";
147                 UNREACHABLE();
148             }
149             callInfo->SetCallArg(0, JSTaggedValue(input));
150             ContainersDeque::InsertFront(callInfo);
151             auto callInfo1 = CreateEcmaRuntimeCallInfo(thread, 4);
152             callInfo1->SetFunction(JSTaggedValue::Undefined());
153             callInfo1->SetThis(deque.GetTaggedValue());
154             ContainersDeque::GetFirst(callInfo1);
155         }
156         JSNApi::DestroyJSVM(vm);
157         return;
158     }
159 
ContainersDequeGetLastFuzzTest(const uint8_t * data,size_t size)160     static void ContainersDequeGetLastFuzzTest(const uint8_t* data, size_t size)
161     {
162         RuntimeOption option;
163         option.SetLogLevel(common::LOG_LEVEL::ERROR);
164         EcmaVM *vm = JSNApi::CreateJSVM(option);
165         {
166             JsiFastNativeScope scope(vm);
167             auto thread = vm->GetAssociatedJSThread();
168 
169             JSHandle<JSAPIDeque> deque = CreateJSAPIDeque(thread);
170             auto callInfo = CreateEcmaRuntimeCallInfo(thread, 8);
171             callInfo->SetFunction(JSTaggedValue::Undefined());
172             callInfo->SetThis(deque.GetTaggedValue());
173 
174             unsigned int input = 0;
175             if (size <= 0) {
176                 return;
177             }
178             if (size > MAXBYTELEN) {
179                 size = MAXBYTELEN;
180             }
181             if (memcpy_s(&input, MAXBYTELEN, data, size) != 0) {
182                 std::cout << "memcpy_s failed!";
183                 UNREACHABLE();
184             }
185             callInfo->SetCallArg(0, JSTaggedValue(input));
186 
187             ContainersDeque::InsertFront(callInfo);
188 
189             auto callInfo1 = CreateEcmaRuntimeCallInfo(thread, 4);
190             callInfo1->SetFunction(JSTaggedValue::Undefined());
191             callInfo1->SetThis(deque.GetTaggedValue());
192             ContainersDeque::GetLast(callInfo1);
193         }
194         JSNApi::DestroyJSVM(vm);
195         return;
196     }
197 
ContainersDequeInsertEndFuzzTest(const uint8_t * data,size_t size)198     static void ContainersDequeInsertEndFuzzTest(const uint8_t* data, size_t size)
199     {
200         RuntimeOption option;
201         option.SetLogLevel(common::LOG_LEVEL::ERROR);
202         EcmaVM *vm = JSNApi::CreateJSVM(option);
203         {
204             JsiFastNativeScope scope(vm);
205             auto thread = vm->GetAssociatedJSThread();
206 
207             JSHandle<JSAPIDeque> deque = CreateJSAPIDeque(thread);
208             auto callInfo = CreateEcmaRuntimeCallInfo(thread, 8);
209             callInfo->SetFunction(JSTaggedValue::Undefined());
210             callInfo->SetThis(deque.GetTaggedValue());
211 
212             unsigned int input = 0;
213             if (size <= 0) {
214                 return;
215             }
216             if (size > MAXBYTELEN) {
217                 size = MAXBYTELEN;
218             }
219             if (memcpy_s(&input, MAXBYTELEN, data, size) != 0) {
220                 std::cout << "memcpy_s failed!";
221                 UNREACHABLE();
222             }
223             callInfo->SetCallArg(0, JSTaggedValue(input));
224             ContainersDeque::InsertEnd(callInfo);
225         }
226         JSNApi::DestroyJSVM(vm);
227         return;
228     }
229 
ContainersDequeHasFuzzTest(const uint8_t * data,size_t size)230     static void ContainersDequeHasFuzzTest(const uint8_t* data, size_t size)
231     {
232         RuntimeOption option;
233         option.SetLogLevel(common::LOG_LEVEL::ERROR);
234         EcmaVM *vm = JSNApi::CreateJSVM(option);
235         {
236             JsiFastNativeScope scope(vm);
237             auto thread = vm->GetAssociatedJSThread();
238 
239             JSHandle<JSAPIDeque> deque = CreateJSAPIDeque(thread);
240             auto callInfo = CreateEcmaRuntimeCallInfo(thread, 8);
241             callInfo->SetFunction(JSTaggedValue::Undefined());
242             callInfo->SetThis(deque.GetTaggedValue());
243 
244             unsigned int input = 0;
245             if (size <= 0) {
246                 return;
247             }
248             if (size > MAXBYTELEN) {
249                 size = MAXBYTELEN;
250             }
251             if (memcpy_s(&input, MAXBYTELEN, data, size) != 0) {
252                 std::cout << "memcpy_s failed!";
253                 UNREACHABLE();
254             }
255             callInfo->SetCallArg(0, JSTaggedValue(input));
256 
257             ContainersDeque::InsertEnd(callInfo);
258 
259             auto callInfo1 = CreateEcmaRuntimeCallInfo(thread, 8);
260             callInfo1->SetFunction(JSTaggedValue::Undefined());
261             callInfo1->SetThis(deque.GetTaggedValue());
262             callInfo1->SetCallArg(0, JSTaggedValue(input));
263             ContainersDeque::Has(callInfo1);
264         }
265         JSNApi::DestroyJSVM(vm);
266         return;
267     }
268 
ContainersDequePopFirstFuzzTest(const uint8_t * data,size_t size)269     static void ContainersDequePopFirstFuzzTest(const uint8_t* data, size_t size)
270     {
271         RuntimeOption option;
272         option.SetLogLevel(common::LOG_LEVEL::ERROR);
273         EcmaVM *vm = JSNApi::CreateJSVM(option);
274         {
275             JsiFastNativeScope scope(vm);
276             auto thread = vm->GetAssociatedJSThread();
277 
278             JSHandle<JSAPIDeque> deque = CreateJSAPIDeque(thread);
279             auto callInfo = CreateEcmaRuntimeCallInfo(thread, 8);
280             callInfo->SetFunction(JSTaggedValue::Undefined());
281             callInfo->SetThis(deque.GetTaggedValue());
282 
283             unsigned int input = 0;
284             if (size <= 0) {
285                 return;
286             }
287             if (size > MAXBYTELEN) {
288                 size = MAXBYTELEN;
289             }
290             if (memcpy_s(&input, MAXBYTELEN, data, size) != 0) {
291                 std::cout << "memcpy_s failed!";
292                 UNREACHABLE();
293             }
294             callInfo->SetCallArg(0, JSTaggedValue(input));
295             ContainersDeque::InsertFront(callInfo);
296             auto callInfo1 = CreateEcmaRuntimeCallInfo(thread, 4);
297             callInfo1->SetFunction(JSTaggedValue::Undefined());
298             callInfo1->SetThis(deque.GetTaggedValue());
299             ContainersDeque::PopFirst(callInfo1);
300         }
301         JSNApi::DestroyJSVM(vm);
302         return;
303     }
304 
ContainersDequePopLastFuzzTest(const uint8_t * data,size_t size)305     static void ContainersDequePopLastFuzzTest(const uint8_t* data, size_t size)
306     {
307         RuntimeOption option;
308         option.SetLogLevel(common::LOG_LEVEL::ERROR);
309         EcmaVM *vm = JSNApi::CreateJSVM(option);
310         {
311             JsiFastNativeScope scope(vm);
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             ContainersDeque::InsertFront(callInfo);
332             auto callInfo1 = CreateEcmaRuntimeCallInfo(thread, 4);
333             callInfo1->SetFunction(JSTaggedValue::Undefined());
334             callInfo1->SetThis(deque.GetTaggedValue());
335             ContainersDeque::PopLast(callInfo1);
336         }
337         JSNApi::DestroyJSVM(vm);
338         return;
339     }
340 
ContainersDequeIteratorFuzzTest(const uint8_t * data,size_t size)341     static void ContainersDequeIteratorFuzzTest(const uint8_t* data, size_t size)
342     {
343         RuntimeOption option;
344         option.SetLogLevel(common::LOG_LEVEL::ERROR);
345         EcmaVM *vm = JSNApi::CreateJSVM(option);
346         {
347             JsiFastNativeScope scope(vm);
348             auto thread = vm->GetAssociatedJSThread();
349 
350             uint32_t input = 0;
351             if (size <= 0) {
352                 return;
353             }
354             if (size > MAXBYTELEN) {
355                 size = MAXBYTELEN;
356             }
357             if (memcpy_s(&input, MAXBYTELEN, data, size) != 0) {
358                 std::cout << "memcpy_s failed!";
359                 UNREACHABLE();
360             }
361 
362             constexpr uint32_t NODE_NUMBERS = 8;
363             JSHandle<JSAPIDeque> deque = CreateJSAPIDeque(thread);
364             for (uint32_t i = 0; i < NODE_NUMBERS; i++) {
365                 auto callInfo = CreateEcmaRuntimeCallInfo(thread, 8);
366                 callInfo->SetFunction(JSTaggedValue::Undefined());
367                 callInfo->SetThis(deque.GetTaggedValue());
368                 callInfo->SetCallArg(0, JSTaggedValue(i + input));
369 
370                 ContainersDeque::InsertEnd(callInfo);
371             }
372 
373             auto callInfo1 = CreateEcmaRuntimeCallInfo(thread, 4);
374             callInfo1->SetFunction(JSTaggedValue::Undefined());
375             callInfo1->SetThis(deque.GetTaggedValue());
376             JSHandle<JSTaggedValue> iterValues(thread, ContainersDeque::GetIteratorObj(callInfo1));
377 
378             JSMutableHandle<JSTaggedValue> result(thread, JSTaggedValue::Undefined());
379             for (uint32_t i = 0; i < NODE_NUMBERS; i++) {
380                 auto callInfo = CreateEcmaRuntimeCallInfo(thread, 4);
381                 callInfo->SetFunction(JSTaggedValue::Undefined());
382                 callInfo->SetThis(iterValues.GetTaggedValue());
383                 result.Update(JSAPIDequeIterator::Next(callInfo));
384             }
385         }
386         JSNApi::DestroyJSVM(vm);
387         return;
388     }
389 };
390 }
391 #endif