1/*
2 * Copyright (c) 2023 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 "jsvaluereffoundationvalue_fuzzer.h"
17#include "ecmascript/base/string_helper.h"
18#include "ecmascript/ecma_string-inl.h"
19#include "ecmascript/napi/include/jsnapi.h"
20
21using namespace panda;
22using namespace panda::ecmascript;
23
24#define MAXBYTELEN sizeof(int32_t)
25
26namespace OHOS {
27void JSValueRefIsNumberValueFuzzTest(const uint8_t *data, size_t size)
28{
29    RuntimeOption option;
30    option.SetLogLevel(RuntimeOption::LOG_LEVEL::ERROR);
31    EcmaVM *vm = JSNApi::CreateJSVM(option);
32    int key = 0;
33    uint32_t inputUnit32 = 32;
34    if (data == nullptr || size <= 0) {
35        std::cout << "illegal input!";
36        return;
37    }
38    if (size > MAXBYTELEN) {
39        size = MAXBYTELEN;
40    }
41    if (memcpy_s(&key, MAXBYTELEN, data, size) != EOK) {
42        std::cout << "memcpy_s failed!";
43        UNREACHABLE();
44    }
45    Local<IntegerRef> intValue = IntegerRef::New(vm, key);
46    if (memcpy_s(&inputUnit32, MAXBYTELEN, data, size) != EOK) {
47        std::cout << "memcpy_s failed!";
48        UNREACHABLE();
49    }
50    Local<NumberRef> resUnit32 = NumberRef::New(vm, inputUnit32);
51    bool inputBool = true;
52    if (size == 0 || data == nullptr) {
53        inputBool = false;
54    }
55    Local<BooleanRef> resBool = BooleanRef::New(vm, inputBool);
56    Local<StringRef> stringUtf8 = StringRef::NewFromUtf8(vm, (char *)data, (int)size);
57    intValue->IsNumber();
58    resUnit32->IsNumber();
59    resBool->IsNumber();
60    stringUtf8->IsNumber();
61    JSNApi::DestroyJSVM(vm);
62}
63
64void JSValueRefIsStringValueFuzzTest(const uint8_t *data, size_t size)
65{
66    RuntimeOption option;
67    option.SetLogLevel(RuntimeOption::LOG_LEVEL::ERROR);
68    EcmaVM *vm = JSNApi::CreateJSVM(option);
69    if (data == nullptr || size <= 0) {
70        std::cout << "illegal input!";
71        return;
72    }
73    Local<JSValueRef> tag = StringRef::NewFromUtf8(vm, (char *)data, (int)size);
74    tag->IsString(vm);
75    JSNApi::DestroyJSVM(vm);
76}
77
78void JSValueRefWithinInt32ValueFuzzTest(const uint8_t *data, size_t size)
79{
80    RuntimeOption option;
81    option.SetLogLevel(RuntimeOption::LOG_LEVEL::ERROR);
82    EcmaVM *vm = JSNApi::CreateJSVM(option);
83    int number = 0;
84    if (data == nullptr || size <= 0) {
85        std::cout << "illegal input!";
86        return;
87    }
88    if (size > MAXBYTELEN) {
89        size = MAXBYTELEN;
90    }
91    if (memcpy_s(&number, MAXBYTELEN, data, size) != 0) {
92        std::cout << "memcpy_s failed!";
93        UNREACHABLE();
94    }
95    Local<JSValueRef> tag = IntegerRef::New(vm, number);
96    tag->WithinInt32();
97    JSNApi::DestroyJSVM(vm);
98}
99
100Local<JSValueRef> FunCallback(JsiRuntimeCallInfo *info)
101{
102    EscapeLocalScope scope(info->GetVM());
103    return scope.Escape(ArrayRef::New(info->GetVM(), info->GetArgsNumber()));
104}
105
106void JSValueRefIsFunctionValueFuzzTest(const uint8_t *data, size_t size)
107{
108    RuntimeOption option;
109    option.SetLogLevel(RuntimeOption::LOG_LEVEL::ERROR);
110    EcmaVM *vm = JSNApi::CreateJSVM(option);
111    if (data == nullptr || size <= 0) {
112        std::cout << "illegal input!";
113        return;
114    }
115    NativePointerCallback deleter = nullptr;
116    FunctionCallback nativeFunc = FunCallback;
117    Local<FunctionRef> obj(FunctionRef::NewClassFunction(vm, nativeFunc, deleter, (void *)(data + size)));
118    (void)obj->IsFunction(vm);
119    JSNApi::DestroyJSVM(vm);
120}
121
122void JSValueRefIsTypedArrayValueFuzzTest(const uint8_t *data, size_t size)
123{
124    RuntimeOption option;
125    option.SetLogLevel(RuntimeOption::LOG_LEVEL::ERROR);
126    EcmaVM *vm = JSNApi::CreateJSVM(option);
127    int number = 123;
128    if (data == nullptr || size <= 0) {
129        std::cout << "illegal input!";
130        return;
131    }
132    if (size > MAXBYTELEN) {
133        size = MAXBYTELEN;
134    }
135    if (memcpy_s(&number, MAXBYTELEN, data, size) != 0) {
136        std::cout << "memcpy_s failed!";
137        UNREACHABLE();
138    }
139    Local<JSValueRef> targetUInt = IntegerRef::New(vm, number);
140    targetUInt->IsTypedArray(vm);
141    int32_t input;
142    if (memcpy_s(&input, MAXBYTELEN, data, size) != 0) {
143        std::cout << "memcpy_s failed!";
144        UNREACHABLE();
145    }
146    const int32_t MaxMenory = 1024;
147    if (input > MaxMenory) {
148        input = MaxMenory;
149    }
150    Local<ArrayBufferRef> ref = ArrayBufferRef::New(vm, input);
151    ref->IsArrayBuffer(vm);
152    Local<Uint32ArrayRef> typedArray = Uint32ArrayRef::New(vm, ref, (int32_t)size, (int32_t)size);
153    typedArray->IsTypedArray(vm);
154    JSNApi::DestroyJSVM(vm);
155}
156
157void JSValueRefIsDateValueFuzzTest(const uint8_t *data, size_t size)
158{
159    RuntimeOption option;
160    option.SetLogLevel(RuntimeOption::LOG_LEVEL::ERROR);
161    EcmaVM *vm = JSNApi::CreateJSVM(option);
162    int key = 0;
163    uint32_t inputUnit32 = 32;
164    if (data == nullptr || size <= 0) {
165        std::cout << "illegal input!";
166        return;
167    }
168    if (size > MAXBYTELEN) {
169        size = MAXBYTELEN;
170    }
171    if (memcpy_s(&key, MAXBYTELEN, data, size) != EOK) {
172        std::cout << "memcpy_s failed!";
173        UNREACHABLE();
174    }
175    Local<IntegerRef> intValue = IntegerRef::New(vm, key);
176    if (memcpy_s(&inputUnit32, MAXBYTELEN, data, size) != EOK) {
177        std::cout << "memcpy_s failed!";
178        UNREACHABLE();
179    }
180    Local<NumberRef> resUnit32 = NumberRef::New(vm, inputUnit32);
181    Local<StringRef> stringUtf8 = StringRef::NewFromUtf8(vm, (char *)data, (int)size);
182
183    double timeRef = 1.1;
184    size_t maxByteLen = 8;
185    if (size > maxByteLen) {
186        size = maxByteLen;
187    }
188    if (memcpy_s(&timeRef, maxByteLen, data, size) != EOK) {
189        std::cout << "memcpy_s failed!";
190        UNREACHABLE();
191    }
192    Local<DateRef> dateRef = DateRef::New(vm, timeRef);
193    resUnit32->IsDate(vm);
194    intValue->IsDate(vm);
195    stringUtf8->IsDate(vm);
196    dateRef->IsDate(vm);
197    JSNApi::DestroyJSVM(vm);
198}
199
200void JSValueRefIsErrorValueFuzzTest(const uint8_t *data, size_t size)
201{
202    RuntimeOption option;
203    option.SetLogLevel(RuntimeOption::LOG_LEVEL::ERROR);
204    EcmaVM *vm = JSNApi::CreateJSVM(option);
205    int key = 0;
206    uint32_t inputUnit32 = 32;
207    if (data == nullptr || size <= 0) {
208        std::cout << "illegal input!";
209        return;
210    }
211    if (size > MAXBYTELEN) {
212        size = MAXBYTELEN;
213    }
214    if (memcpy_s(&key, MAXBYTELEN, data, size) != EOK) {
215        std::cout << "memcpy_s failed!";
216        UNREACHABLE();
217    }
218    Local<IntegerRef> intValue = IntegerRef::New(vm, key);
219    if (memcpy_s(&inputUnit32, MAXBYTELEN, data, size) != EOK) {
220        std::cout << "memcpy_s failed!";
221        UNREACHABLE();
222    }
223    Local<NumberRef> resUnit32 = NumberRef::New(vm, inputUnit32);
224    Local<StringRef> stringUtf8 = StringRef::NewFromUtf8(vm, (char *)data, (int)size);
225    Local<JSValueRef> error = Exception::Error(vm, stringUtf8);
226    resUnit32->IsError(vm);
227    intValue->IsError(vm);
228    stringUtf8->IsError(vm);
229    error->IsError(vm);
230    JSNApi::DestroyJSVM(vm);
231}
232
233void JSValueRefToStringValueFuzzTest(const uint8_t *data, size_t size)
234{
235    RuntimeOption option;
236    option.SetLogLevel(RuntimeOption::LOG_LEVEL::ERROR);
237    EcmaVM *vm = JSNApi::CreateJSVM(option);
238    int key = 0;
239    uint32_t inputUnit32 = 32;
240    if (data == nullptr || size <= 0) {
241        std::cout << "illegal input!";
242        return;
243    }
244    if (size > MAXBYTELEN) {
245        size = MAXBYTELEN;
246    }
247    if (memcpy_s(&key, MAXBYTELEN, data, size) != EOK) {
248        std::cout << "memcpy_s failed!";
249        UNREACHABLE();
250    }
251    Local<IntegerRef> intValue = IntegerRef::New(vm, key);
252    if (memcpy_s(&inputUnit32, MAXBYTELEN, data, size) != EOK) {
253        std::cout << "memcpy_s failed!";
254        UNREACHABLE();
255    }
256    Local<NumberRef> resUnit32 = NumberRef::New(vm, inputUnit32);
257    bool inputBool = true;
258    if (size == 0 || data == nullptr) {
259        inputBool = false;
260    }
261    Local<BooleanRef> resBool = BooleanRef::New(vm, inputBool);
262    Local<StringRef> stringUtf8 = StringRef::NewFromUtf8(vm, (char *)data, (int)size);
263    Local<JSValueRef> toTarget(stringUtf8);
264    intValue->ToString(vm);
265    resUnit32->ToString(vm);
266    resBool->ToString(vm);
267    toTarget->ToString(vm);
268    JSNApi::DestroyJSVM(vm);
269}
270}
271
272
273// Fuzzer entry point.
274extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
275{
276    // Run your code on data.
277    OHOS::JSValueRefIsNumberValueFuzzTest(data, size);
278    OHOS::JSValueRefIsStringValueFuzzTest(data, size);
279    OHOS::JSValueRefWithinInt32ValueFuzzTest(data, size);
280    OHOS::JSValueRefIsFunctionValueFuzzTest(data, size);
281    OHOS::JSValueRefIsTypedArrayValueFuzzTest(data, size);
282    OHOS::JSValueRefIsDateValueFuzzTest(data, size);
283    OHOS::JSValueRefIsErrorValueFuzzTest(data, size);
284    OHOS::JSValueRefToStringValueFuzzTest(data, size);
285    return 0;
286}
287