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#include "containerslightweightmapvalues_fuzzer.h"
17
18#include "ecmascript/containers/containers_lightweightmap.h"
19#include "ecmascript/containers/containers_private.h"
20#include "ecmascript/ecma_string-inl.h"
21#include "ecmascript/ecma_vm.h"
22#include "ecmascript/global_env.h"
23#include "ecmascript/js_handle.h"
24#include "ecmascript/napi/include/jsnapi.h"
25#include "ecmascript/js_api/js_api_lightweightmap.h"
26#include "ecmascript/js_api/js_api_lightweightmap_iterator.h"
27
28using namespace panda;
29using namespace panda::test;
30using namespace panda::ecmascript;
31using namespace panda::ecmascript::containers;
32
33namespace OHOS {
34
35    JSFunction *JSObjectCreate(JSThread *thread)
36    {
37        EcmaVM *ecmaVM = thread->GetEcmaVM();
38        JSHandle<GlobalEnv> globalEnv = ecmaVM->GetGlobalEnv();
39        return globalEnv->GetObjectFunction().GetObject<JSFunction>();
40    }
41
42    EcmaRuntimeCallInfo *CreateEcmaRuntimeCallInfo(JSThread *thread, uint32_t numArgs)
43    {
44        auto factory = thread->GetEcmaVM()->GetFactory();
45        JSHandle<JSTaggedValue> hclass(thread, JSObjectCreate(thread));
46        JSHandle<JSTaggedValue> callee(factory->NewJSObjectByConstructor(JSHandle<JSFunction>::Cast(hclass), hclass));
47        JSHandle<JSTaggedValue> undefined = thread->GlobalConstants()->GetHandledUndefined();
48        EcmaRuntimeCallInfo *objCallInfo =
49            EcmaInterpreter::NewRuntimeCallInfo(thread, undefined, callee, undefined, numArgs);
50        return objCallInfo;
51    }
52
53    JSTaggedValue InitializeLightWeightMapConstructor(JSThread *thread)
54    {
55        auto factory = thread->GetEcmaVM()->GetFactory();
56        JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
57        JSHandle<JSTaggedValue> globalObject = env->GetJSGlobalObject();
58        JSHandle<JSTaggedValue> key(factory->NewFromASCII("ArkPrivate"));
59        JSHandle<JSTaggedValue> value =
60            JSObject::GetProperty(thread, JSHandle<JSTaggedValue>(globalObject), key).GetValue();
61
62        auto objCallInfo = CreateEcmaRuntimeCallInfo(thread, 6); // 6 : means the argv length
63        objCallInfo->SetFunction(JSTaggedValue::Undefined());
64        objCallInfo->SetThis(value.GetTaggedValue());
65        objCallInfo->SetCallArg(0, JSTaggedValue(static_cast<int>(ContainerTag::LightWeightMap)));
66        JSTaggedValue result = ContainersPrivate::Load(objCallInfo);
67
68        return result;
69    }
70
71    JSHandle<JSAPILightWeightMap> CreateJSAPILightWeightMap(JSThread *thread)
72    {
73        JSHandle<JSFunction> newTarget(thread, InitializeLightWeightMapConstructor(thread));
74        auto objCallInfo = CreateEcmaRuntimeCallInfo(thread, 4);
75        objCallInfo->SetFunction(newTarget.GetTaggedValue());
76        objCallInfo->SetNewTarget(newTarget.GetTaggedValue());
77        objCallInfo->SetThis(JSTaggedValue::Undefined());
78
79        JSTaggedValue result = ContainersLightWeightMap::LightWeightMapConstructor(objCallInfo);
80        JSHandle<JSAPILightWeightMap> map(thread, result);
81        return map;
82    }
83
84    void ContainersLightWeightMapValuesFuzzTest(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
93            if (size <= 0) {
94                return;
95            }
96            double input = 0;
97            const double maxByteLen = 4;
98            if (size > maxByteLen) {
99                size = maxByteLen;
100            }
101            if (memcpy_s(&input, maxByteLen, data, size) != 0) {
102                std::cout << "memcpy_s failed!";
103                UNREACHABLE();
104            }
105            JSHandle<JSAPILightWeightMap> lightWeightMap = CreateJSAPILightWeightMap(thread);
106
107            EcmaRuntimeCallInfo *callInfo1 = CreateEcmaRuntimeCallInfo(thread, 8);
108            callInfo1->SetFunction(JSTaggedValue::Undefined());
109            callInfo1->SetThis(lightWeightMap.GetTaggedValue());
110            callInfo1->SetCallArg(0, JSTaggedValue(input));
111            callInfo1->SetCallArg(1, JSTaggedValue(input));
112            ContainersLightWeightMap::Set(callInfo1);
113
114            JSMutableHandle<JSTaggedValue> result(thread, JSTaggedValue::Undefined());
115            EcmaRuntimeCallInfo *callInfo2 = CreateEcmaRuntimeCallInfo(thread, 4);
116            callInfo2->SetFunction(JSTaggedValue::Undefined());
117            callInfo2->SetThis(lightWeightMap.GetTaggedValue());
118            JSHandle<JSTaggedValue> iterValues(thread, ContainersLightWeightMap::Values(callInfo2));
119
120            EcmaRuntimeCallInfo *callInfo3 = CreateEcmaRuntimeCallInfo(thread, 4);
121            callInfo3->SetFunction(JSTaggedValue::Undefined());
122            callInfo3->SetThis(iterValues.GetTaggedValue());
123            result.Update(JSAPILightWeightMapIterator::Next(callInfo3));
124            JSHandle<JSTaggedValue> valuesHandle = JSIterator::IteratorValue(thread, result);
125
126            EcmaRuntimeCallInfo *callInfo4 = CreateEcmaRuntimeCallInfo(thread, 6);
127            callInfo4->SetFunction(JSTaggedValue::Undefined());
128            callInfo4->SetThis(lightWeightMap.GetTaggedValue());
129            callInfo4->SetCallArg(0, valuesHandle.GetTaggedValue());
130            ContainersLightWeightMap::HasValue(callInfo4);
131        }
132        JSNApi::DestroyJSVM(vm);
133    }
134}
135
136// Fuzzer entry point.
137extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size)
138{
139    // Run your code on data.
140    OHOS::ContainersLightWeightMapValuesFuzzTest(data, size);
141    return 0;
142}