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 35namespace panda::ecmascript { 36using namespace panda::ecmascript::containers; 37class ContainersDequeFuzzTestHelper { 38public: 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 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 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 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 { 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: 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 124 static void ContainersDequeForEachFuzzTest(const uint8_t* data, size_t size) 125 { 126 uint32_t input = 0; 127 if (size <= 0) { 128 return; 129 } 130 if (size > MAXBYTELEN) { 131 size = MAXBYTELEN; 132 } 133 if (memcpy_s(&input, MAXBYTELEN, data, size) != 0) { 134 std::cout << "memcpy_s failed!"; 135 UNREACHABLE(); 136 } 137 138 RuntimeOption option; 139 option.SetLogLevel(RuntimeOption::LOG_LEVEL::ERROR); 140 EcmaVM *vm = JSNApi::CreateJSVM(option); 141 { 142 JsiFastNativeScope scope(vm); 143 auto thread = vm->GetAssociatedJSThread(); 144 145 constexpr uint32_t NODE_NUMBERS = 8; 146 JSHandle<JSAPIDeque> deque = CreateJSAPIDeque(thread); 147 for (uint32_t i = 0; i < NODE_NUMBERS; i++) { 148 auto callInfo = CreateEcmaRuntimeCallInfo(thread, 8); 149 callInfo->SetFunction(JSTaggedValue::Undefined()); 150 callInfo->SetThis(deque.GetTaggedValue()); 151 callInfo->SetCallArg(0, JSTaggedValue(i + input)); 152 ContainersDeque::InsertFront(callInfo); 153 } 154 155 JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv(); 156 JSHandle<JSFunction> func = thread->GetEcmaVM()->GetFactory()->NewJSFunction(env, 157 reinterpret_cast<void *>(TestClass::TestForEachFunc)); 158 auto callInfo = CreateEcmaRuntimeCallInfo(thread, 8); 159 callInfo->SetFunction(JSTaggedValue::Undefined()); 160 callInfo->SetThis(deque.GetTaggedValue()); 161 callInfo->SetCallArg(0, func.GetTaggedValue()); 162 callInfo->SetCallArg(1, deque.GetTaggedValue()); 163 ContainersDeque::ForEach(callInfo); 164 } 165 JSNApi::DestroyJSVM(vm); 166 } 167 168 static void ContainersDequeGetFirstFuzzTest(const uint8_t* data, size_t size) 169 { 170 RuntimeOption option; 171 option.SetLogLevel(RuntimeOption::LOG_LEVEL::ERROR); 172 EcmaVM *vm = JSNApi::CreateJSVM(option); 173 { 174 JsiFastNativeScope scope(vm); 175 auto thread = vm->GetAssociatedJSThread(); 176 177 JSHandle<JSAPIDeque> deque = CreateJSAPIDeque(thread); 178 auto callInfo = CreateEcmaRuntimeCallInfo(thread, 8); 179 callInfo->SetFunction(JSTaggedValue::Undefined()); 180 callInfo->SetThis(deque.GetTaggedValue()); 181 182 unsigned int input = 0; 183 if (size <= 0) { 184 return; 185 } 186 if (size > MAXBYTELEN) { 187 size = MAXBYTELEN; 188 } 189 if (memcpy_s(&input, MAXBYTELEN, data, size) != 0) { 190 std::cout << "memcpy_s failed!"; 191 UNREACHABLE(); 192 } 193 callInfo->SetCallArg(0, JSTaggedValue(input)); 194 ContainersDeque::InsertFront(callInfo); 195 auto callInfo1 = CreateEcmaRuntimeCallInfo(thread, 4); 196 callInfo1->SetFunction(JSTaggedValue::Undefined()); 197 callInfo1->SetThis(deque.GetTaggedValue()); 198 ContainersDeque::GetFirst(callInfo1); 199 } 200 JSNApi::DestroyJSVM(vm); 201 return; 202 } 203 204 static void ContainersDequeGetLastFuzzTest(const uint8_t* data, size_t size) 205 { 206 RuntimeOption option; 207 option.SetLogLevel(RuntimeOption::LOG_LEVEL::ERROR); 208 EcmaVM *vm = JSNApi::CreateJSVM(option); 209 { 210 JsiFastNativeScope scope(vm); 211 auto thread = vm->GetAssociatedJSThread(); 212 213 JSHandle<JSAPIDeque> deque = CreateJSAPIDeque(thread); 214 auto callInfo = CreateEcmaRuntimeCallInfo(thread, 8); 215 callInfo->SetFunction(JSTaggedValue::Undefined()); 216 callInfo->SetThis(deque.GetTaggedValue()); 217 218 unsigned int input = 0; 219 if (size <= 0) { 220 return; 221 } 222 if (size > MAXBYTELEN) { 223 size = MAXBYTELEN; 224 } 225 if (memcpy_s(&input, MAXBYTELEN, data, size) != 0) { 226 std::cout << "memcpy_s failed!"; 227 UNREACHABLE(); 228 } 229 callInfo->SetCallArg(0, JSTaggedValue(input)); 230 231 ContainersDeque::InsertFront(callInfo); 232 233 auto callInfo1 = CreateEcmaRuntimeCallInfo(thread, 4); 234 callInfo1->SetFunction(JSTaggedValue::Undefined()); 235 callInfo1->SetThis(deque.GetTaggedValue()); 236 ContainersDeque::GetLast(callInfo1); 237 } 238 JSNApi::DestroyJSVM(vm); 239 return; 240 } 241 242 static void ContainersDequeInsertEndFuzzTest(const uint8_t* data, size_t size) 243 { 244 RuntimeOption option; 245 option.SetLogLevel(RuntimeOption::LOG_LEVEL::ERROR); 246 EcmaVM *vm = JSNApi::CreateJSVM(option); 247 { 248 JsiFastNativeScope scope(vm); 249 auto thread = vm->GetAssociatedJSThread(); 250 251 JSHandle<JSAPIDeque> deque = CreateJSAPIDeque(thread); 252 auto callInfo = CreateEcmaRuntimeCallInfo(thread, 8); 253 callInfo->SetFunction(JSTaggedValue::Undefined()); 254 callInfo->SetThis(deque.GetTaggedValue()); 255 256 unsigned int input = 0; 257 if (size <= 0) { 258 return; 259 } 260 if (size > MAXBYTELEN) { 261 size = MAXBYTELEN; 262 } 263 if (memcpy_s(&input, MAXBYTELEN, data, size) != 0) { 264 std::cout << "memcpy_s failed!"; 265 UNREACHABLE(); 266 } 267 callInfo->SetCallArg(0, JSTaggedValue(input)); 268 ContainersDeque::InsertEnd(callInfo); 269 } 270 JSNApi::DestroyJSVM(vm); 271 return; 272 } 273 274 static void ContainersDequeHasFuzzTest(const uint8_t* data, size_t size) 275 { 276 RuntimeOption option; 277 option.SetLogLevel(RuntimeOption::LOG_LEVEL::ERROR); 278 EcmaVM *vm = JSNApi::CreateJSVM(option); 279 { 280 JsiFastNativeScope scope(vm); 281 auto thread = vm->GetAssociatedJSThread(); 282 283 JSHandle<JSAPIDeque> deque = CreateJSAPIDeque(thread); 284 auto callInfo = CreateEcmaRuntimeCallInfo(thread, 8); 285 callInfo->SetFunction(JSTaggedValue::Undefined()); 286 callInfo->SetThis(deque.GetTaggedValue()); 287 288 unsigned int input = 0; 289 if (size <= 0) { 290 return; 291 } 292 if (size > MAXBYTELEN) { 293 size = MAXBYTELEN; 294 } 295 if (memcpy_s(&input, MAXBYTELEN, data, size) != 0) { 296 std::cout << "memcpy_s failed!"; 297 UNREACHABLE(); 298 } 299 callInfo->SetCallArg(0, JSTaggedValue(input)); 300 301 ContainersDeque::InsertEnd(callInfo); 302 303 auto callInfo1 = CreateEcmaRuntimeCallInfo(thread, 8); 304 callInfo1->SetFunction(JSTaggedValue::Undefined()); 305 callInfo1->SetThis(deque.GetTaggedValue()); 306 callInfo1->SetCallArg(0, JSTaggedValue(input)); 307 ContainersDeque::Has(callInfo1); 308 } 309 JSNApi::DestroyJSVM(vm); 310 return; 311 } 312 313 static void ContainersDequePopFirstFuzzTest(const uint8_t* data, size_t size) 314 { 315 RuntimeOption option; 316 option.SetLogLevel(RuntimeOption::LOG_LEVEL::ERROR); 317 EcmaVM *vm = JSNApi::CreateJSVM(option); 318 { 319 JsiFastNativeScope scope(vm); 320 auto thread = vm->GetAssociatedJSThread(); 321 322 JSHandle<JSAPIDeque> deque = CreateJSAPIDeque(thread); 323 auto callInfo = CreateEcmaRuntimeCallInfo(thread, 8); 324 callInfo->SetFunction(JSTaggedValue::Undefined()); 325 callInfo->SetThis(deque.GetTaggedValue()); 326 327 unsigned int input = 0; 328 if (size <= 0) { 329 return; 330 } 331 if (size > MAXBYTELEN) { 332 size = MAXBYTELEN; 333 } 334 if (memcpy_s(&input, MAXBYTELEN, data, size) != 0) { 335 std::cout << "memcpy_s failed!"; 336 UNREACHABLE(); 337 } 338 callInfo->SetCallArg(0, JSTaggedValue(input)); 339 ContainersDeque::InsertFront(callInfo); 340 auto callInfo1 = CreateEcmaRuntimeCallInfo(thread, 4); 341 callInfo1->SetFunction(JSTaggedValue::Undefined()); 342 callInfo1->SetThis(deque.GetTaggedValue()); 343 ContainersDeque::PopFirst(callInfo1); 344 } 345 JSNApi::DestroyJSVM(vm); 346 return; 347 } 348 349 static void ContainersDequePopLastFuzzTest(const uint8_t* data, size_t size) 350 { 351 RuntimeOption option; 352 option.SetLogLevel(RuntimeOption::LOG_LEVEL::ERROR); 353 EcmaVM *vm = JSNApi::CreateJSVM(option); 354 { 355 JsiFastNativeScope scope(vm); 356 auto thread = vm->GetAssociatedJSThread(); 357 358 JSHandle<JSAPIDeque> deque = CreateJSAPIDeque(thread); 359 auto callInfo = CreateEcmaRuntimeCallInfo(thread, 8); 360 callInfo->SetFunction(JSTaggedValue::Undefined()); 361 callInfo->SetThis(deque.GetTaggedValue()); 362 363 unsigned int input = 0; 364 if (size <= 0) { 365 return; 366 } 367 if (size > MAXBYTELEN) { 368 size = MAXBYTELEN; 369 } 370 if (memcpy_s(&input, MAXBYTELEN, data, size) != 0) { 371 std::cout << "memcpy_s failed!"; 372 UNREACHABLE(); 373 } 374 callInfo->SetCallArg(0, JSTaggedValue(input)); 375 ContainersDeque::InsertFront(callInfo); 376 auto callInfo1 = CreateEcmaRuntimeCallInfo(thread, 4); 377 callInfo1->SetFunction(JSTaggedValue::Undefined()); 378 callInfo1->SetThis(deque.GetTaggedValue()); 379 ContainersDeque::PopLast(callInfo1); 380 } 381 JSNApi::DestroyJSVM(vm); 382 return; 383 } 384 385 static void ContainersDequeIteratorFuzzTest(const uint8_t* data, size_t size) 386 { 387 RuntimeOption option; 388 option.SetLogLevel(RuntimeOption::LOG_LEVEL::ERROR); 389 EcmaVM *vm = JSNApi::CreateJSVM(option); 390 { 391 JsiFastNativeScope scope(vm); 392 auto thread = vm->GetAssociatedJSThread(); 393 394 uint32_t input = 0; 395 if (size <= 0) { 396 return; 397 } 398 if (size > MAXBYTELEN) { 399 size = MAXBYTELEN; 400 } 401 if (memcpy_s(&input, MAXBYTELEN, data, size) != 0) { 402 std::cout << "memcpy_s failed!"; 403 UNREACHABLE(); 404 } 405 406 constexpr uint32_t NODE_NUMBERS = 8; 407 JSHandle<JSAPIDeque> deque = CreateJSAPIDeque(thread); 408 for (uint32_t i = 0; i < NODE_NUMBERS; i++) { 409 auto callInfo = CreateEcmaRuntimeCallInfo(thread, 8); 410 callInfo->SetFunction(JSTaggedValue::Undefined()); 411 callInfo->SetThis(deque.GetTaggedValue()); 412 callInfo->SetCallArg(0, JSTaggedValue(i + input)); 413 414 ContainersDeque::InsertEnd(callInfo); 415 } 416 417 auto callInfo1 = CreateEcmaRuntimeCallInfo(thread, 4); 418 callInfo1->SetFunction(JSTaggedValue::Undefined()); 419 callInfo1->SetThis(deque.GetTaggedValue()); 420 JSHandle<JSTaggedValue> iterValues(thread, ContainersDeque::GetIteratorObj(callInfo1)); 421 422 JSMutableHandle<JSTaggedValue> result(thread, JSTaggedValue::Undefined()); 423 for (uint32_t i = 0; i < NODE_NUMBERS; i++) { 424 auto callInfo = CreateEcmaRuntimeCallInfo(thread, 4); 425 callInfo->SetFunction(JSTaggedValue::Undefined()); 426 callInfo->SetThis(iterValues.GetTaggedValue()); 427 result.Update(JSAPIDequeIterator::Next(callInfo)); 428 } 429 } 430 JSNApi::DestroyJSVM(vm); 431 return; 432 } 433}; 434} 435#endif