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 <cstring>
17#include <map>
18#include <securec.h>
19#include <string>
20#include <vector>
21
22#include "netstack_log.h"
23#include "secure_char.h"
24#include "websocket_client_innerapi.h"
25
26namespace OHOS {
27namespace NetStack {
28namespace WebSocketClient {
29namespace {
30OpenOptions openOptions;
31std::map<std::string, std::string> headers = {
32    {"Content-Type", "application/json"},
33    {"Authorization", "Bearer your_token_here"},
34};
35const uint8_t *g_baseFuzzData = nullptr;
36size_t g_baseFuzzSize = 0;
37size_t g_baseFuzzPos = 0;
38[[maybe_unused]] constexpr size_t STR_LEN = 255;
39} // namespace
40template <class T> T GetData()
41{
42    T object{};
43    size_t objectSize = sizeof(object);
44    if (g_baseFuzzData == nullptr || g_baseFuzzSize <= g_baseFuzzPos || objectSize > g_baseFuzzSize - g_baseFuzzPos) {
45        return object;
46    }
47    errno_t ret = memcpy_s(&object, objectSize, g_baseFuzzData + g_baseFuzzPos, objectSize);
48    if (ret != EOK) {
49        return object;
50    }
51    g_baseFuzzPos += objectSize;
52    return object;
53}
54
55void SetGlobalFuzzData(const uint8_t *data, size_t size)
56{
57    g_baseFuzzData = data;
58    g_baseFuzzSize = size;
59    g_baseFuzzPos = 0;
60}
61
62std::string GetStringFromData(int strlen)
63{
64    if (strlen < 1) {
65        return "";
66    }
67
68    char cstr[strlen];
69    cstr[strlen - 1] = '\0';
70    for (int i = 0; i < strlen - 1; i++) {
71        cstr[i] = GetData<char>();
72    }
73    std::string str(cstr);
74    return str;
75}
76
77static void OnMessage(WebSocketClient *client, const std::string &data, size_t length) {}
78
79static void OnOpen(WebSocketClient *client, OpenResult openResult) {}
80
81static void OnError(WebSocketClient *client, ErrorResult error) {}
82
83static void OnClose(WebSocketClient *client, CloseResult closeResult) {}
84
85void SetRequestOptionsTest(const uint8_t *data, size_t size)
86{
87    if ((data == nullptr) || (size < 1)) {
88        return;
89    }
90    SetGlobalFuzzData(data, size);
91    std::string str = GetStringFromData(STR_LEN);
92    openOptions.headers["Content-Type"] = str;
93    openOptions.headers["Authorization"] = str;
94    WebSocketClient *client = new WebSocketClient();
95    client->Registcallback(OnOpen, OnMessage, OnError, OnClose);
96    client->Connect("www.baidu.com", openOptions);
97}
98
99void SetConnectUrlTest(const uint8_t *data, size_t size)
100{
101    if (size < 1 || data == nullptr) {
102        return;
103    }
104    SetGlobalFuzzData(data, size);
105    std::string str = GetStringFromData(STR_LEN);
106    openOptions.headers["Authorization"] = "Bearer your_token_here";
107    openOptions.headers["Content-Type"] = "application/json";
108    WebSocketClient *client = new WebSocketClient();
109    client->Registcallback(OnOpen, OnMessage, OnError, OnClose);
110    client->Connect(str, openOptions);
111}
112
113void SetSendDataTest(const uint8_t *data, size_t size)
114{
115    if ((data == nullptr) || (size < 1)) {
116        return;
117    }
118    openOptions.headers["Authorization"] = "Bearer your_token_here";
119    SetGlobalFuzzData(data, size);
120    std::string str = GetStringFromData(STR_LEN);
121    openOptions.headers["Content-Type"] = "application/json";
122    WebSocketClient *client = new WebSocketClient();
123    client->Registcallback(OnOpen, OnMessage, OnError, OnClose);
124    client->Connect("www.baidu.com", openOptions);
125    const char *data1 = str.c_str();
126    int32_t sendLength = std::strlen(data1);
127    client->Send(const_cast<char *>(data1), sendLength);
128}
129
130void SetSendDataLengthTest(const uint8_t *data, size_t size)
131{
132    if ((data == nullptr) || (size < 1)) {
133        return;
134    }
135    SetGlobalFuzzData(data, size);
136    openOptions.headers["Content-Type"] = "application/json";
137    openOptions.headers["Authorization"] = "Bearer your_token_here";
138    WebSocketClient *client = new WebSocketClient();
139    client->Registcallback(OnOpen, OnMessage, OnError, OnClose);
140    client->Connect("www.baidu.com", openOptions);
141    const char *data1 = "Hello,world!";
142    client->Send(const_cast<char *>(data1), size);
143}
144
145void SetCloseOptionTest(const uint8_t *data, size_t size)
146{
147    if ((data == nullptr) || (size < 1)) {
148        return;
149    }
150    openOptions.headers["Content-Type"] = "application/json";
151    openOptions.headers["Authorization"] = "Bearer your_token_here";
152    SetGlobalFuzzData(data, size);
153    std::string str = GetStringFromData(STR_LEN);
154
155    WebSocketClient *client = new WebSocketClient();
156    client->Registcallback(OnOpen, OnMessage, OnError, OnClose);
157    client->Connect("www.baidu.com", openOptions);
158    CloseOption CloseOptions;
159    CloseOptions.code = size;
160    CloseOptions.reason = str.c_str();
161    client->Close(CloseOptions);
162}
163
164} // namespace WebSocketClient
165} // namespace NetStack
166} // namespace OHOS
167
168/* Fuzzer entry point */
169extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
170{
171    /* Run your code on data */
172    OHOS::NetStack::WebSocketClient::SetRequestOptionsTest(data, size);
173    OHOS::NetStack::WebSocketClient::SetConnectUrlTest(data, size);
174    OHOS::NetStack::WebSocketClient::SetSendDataTest(data, size);
175    OHOS::NetStack::WebSocketClient::SetSendDataLengthTest(data, size);
176    OHOS::NetStack::WebSocketClient::SetCloseOptionTest(data, size);
177    return 0;
178}