1/*
2 * Copyright (c) 2024 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 "ChangeJsonUtil.h"
17#include <random>
18#include <fstream>
19#include <iostream>
20#include "secodeFuzz.h"
21#include "cJSON.h"
22#include "securec.h"
23using namespace fuzztest;
24
25namespace {
26const int DEFAULT_LENGTH = 1000;
27const int DEFAULT_INT = 1000;
28const std::string DEFAULT_STRING = "aaaa";
29}
30
31void ChangeJsonUtil::ModifyObject(cJSON *object, uint64_t& idx)
32{
33    if (!object) {
34        return;
35    }
36    cJSON *item = nullptr;
37    cJSON_ArrayForEach(item, object) {
38        if (item->type == cJSON_String) {
39            std::string strVal = DT_SetGetString(&g_Element[idx], strlen(item->valuestring) + 1, DEFAULT_LENGTH,
40                (char*)item->valuestring);
41            idx++;
42            if (item->valuestring != nullptr) {
43                cJSON_free(item->valuestring); // 释放原字符串内存
44            }
45            item->valuestring = nullptr;
46            int length = strVal.length() + 1;
47
48            void* ptr = malloc(length * sizeof(char));
49            if (ptr != nullptr) {
50                item->valuestring = reinterpret_cast<char*>(ptr);
51            }
52            errno_t ret1 = strcpy_s(item->valuestring, length, strVal.c_str()); // 复制字符串内容
53            if (ret1 != EOK) {
54                printf("strcpy_s in modifyObject copy error");
55            }
56        } else if (item->type == cJSON_Number) {
57            int intVal = *(s32 *)DT_SetGetS32(&g_Element[idx], item->valueint);
58            idx++;
59            item->valueint = intVal;
60        } else if (item->type == cJSON_True || item->type == cJSON_False) {
61            std::random_device rd;
62            std::mt19937 gen(rd());
63            std::bernoulli_distribution distribution(0.5); // 0.5 is probability to generate true or false
64            bool ret = distribution(gen);
65            item->type = ret ? cJSON_True : cJSON_False;
66        } else if (item->type == cJSON_Object) {
67            cJSON *arrayItem = nullptr;
68            cJSON_ArrayForEach(arrayItem, item) {
69                ModifyObject(arrayItem, idx);
70            }
71        } else if (item->type == cJSON_Array) {
72            cJSON *objItem = nullptr;
73            cJSON_ArrayForEach(objItem, item) {
74                ModifyObject(objItem, idx);
75            }
76        }
77    }
78}
79
80void ChangeJsonUtil::ModifyObject4ChangeType(cJSON *object, uint64_t& idx)
81{
82    if (!object) {
83        return;
84    }
85    cJSON *item = nullptr;
86    cJSON_ArrayForEach(item, object) {
87        if (item->type == cJSON_String) {
88            int32_t intValue = *(s32 *)DT_SetGetS32(&g_Element[idx], DEFAULT_INT);
89            idx++;
90            item->type = cJSON_Number;
91            item->valuedouble = static_cast<double>(intValue);
92            item->valueint = intValue;
93            if (item->valuestring != nullptr) {
94                cJSON_free(item->valuestring); // 释放原字符串内存
95            }
96            item->valuestring = nullptr;
97        } else if (item->type == cJSON_Number || item->type == cJSON_True || item->type == cJSON_False) {
98            std::string strVal = DT_SetGetString(&g_Element[idx], DEFAULT_STRING.size() + 1, DEFAULT_LENGTH,
99                (char*)DEFAULT_STRING.c_str());
100            idx++;
101            item->type = cJSON_String;
102            int length = strVal.length() + 1;
103            void* ptr = malloc(length * sizeof(char));
104            if (ptr != nullptr) {
105                item->valuestring = reinterpret_cast<char*>(ptr);
106            }
107            errno_t ret2 = strcpy_s(item->valuestring, length, strVal.c_str()); // 复制字符串内容
108            if (ret2 != EOK) {
109                printf("strcpy_s in modifyObject4ChangeType copy error");
110            }
111        } else if (item->type == cJSON_Object) {
112            cJSON *arrayItem = nullptr;
113            cJSON_ArrayForEach(arrayItem, item) {
114                ModifyObject4ChangeType(arrayItem, idx);
115            }
116        } else if (item->type == cJSON_Array) {
117            cJSON *objItem = nullptr;
118            cJSON_ArrayForEach(objItem, item) {
119                ModifyObject4ChangeType(objItem, idx);
120            }
121        }
122    }
123}
124
125void ChangeJsonUtil::WriteFile(std::string filePath, cJSON *object)
126{
127    // Check if cJSON object is valid
128    if (object == nullptr) {
129        std::cerr << "Error: cJSON object is null." << std::endl;
130        return;
131    }
132
133    // Open file stream
134    std::ofstream outFile(filePath);
135    if (!outFile.is_open()) {
136        std::cerr << "Error opening file: " << filePath << std::endl;
137        return;
138    }
139
140    // Convert cJSON object to string
141    char *jsonStr = cJSON_Print(object);
142    if (jsonStr == nullptr) {
143        std::cerr << "Error converting cJSON object to string." << std::endl;
144        outFile.close();
145        return;
146    }
147
148    // Write JSON string to file
149    outFile << jsonStr << std::endl;
150
151    // Clean up
152    cJSON_free(jsonStr);
153    outFile.close();
154
155    std::cout << "JSON content successfully written to file: " << filePath << std::endl;
156}
157
158void ChangeJsonUtil::WriteFile(std::string filePath, std::string str)
159{
160    std::ofstream outFile(filePath);
161    if (!outFile.is_open()) {
162        std::cerr << "Error opening file: " << filePath << std::endl;
163        return;
164    }
165    outFile << str << std::endl;
166    std::cout << "Str content successfully written to file: " << filePath << std::endl;
167}