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