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