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