1 /*
2 * Copyright (c) 2025 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 <fuzzer/FuzzedDataProvider.h>
17
18 #include "grd_api_manager.h"
19 #include "oh_rdb_transaction.h"
20 #include "oh_value_object.h"
21 #include "rdb_errno.h"
22 #include "relational_store.h"
23 #include "relational_store_error_code.h"
24 #include "relational_store_impl.h"
25 #include "ohrdbtransaction_fuzzer.h"
26 #include <iostream>
27
28 using namespace OHOS::NativeRdb;
29 using namespace OHOS::RdbNdk;
30
31 // Helper function to create an OH_Rdb_Config structure with random data
CreateRandomConfig(FuzzedDataProvider & provider)32 OH_Rdb_Config *CreateRandomConfig(FuzzedDataProvider &provider)
33 {
34 OH_Rdb_Config *config = new OH_Rdb_Config();
35 config->selfSize = sizeof(OH_Rdb_Config);
36 config->dataBaseDir = strdup(provider.ConsumeRandomLengthString().c_str());
37 config->storeName = strdup(provider.ConsumeRandomLengthString().c_str());
38 config->bundleName = strdup(provider.ConsumeRandomLengthString().c_str());
39 config->moduleName = strdup(provider.ConsumeRandomLengthString().c_str());
40 config->isEncrypt = provider.ConsumeBool();
41 config->securityLevel = provider.ConsumeIntegralInRange<int>(S1, S4);
42 config->area = provider.ConsumeIntegralInRange<int>(RDB_SECURITY_AREA_EL1, RDB_SECURITY_AREA_EL5);
43 return config;
44 }
45
ReleaseConfig(OH_Rdb_Config * config)46 void ReleaseConfig(OH_Rdb_Config *config)
47 {
48 if (config == nullptr) {
49 return;
50 }
51 if (config->dataBaseDir != nullptr) {
52 free(static_cast<void *>(const_cast<char *>(config->dataBaseDir)));
53 }
54 if (config->storeName != nullptr) {
55 free(static_cast<void *>(const_cast<char *>(config->storeName)));
56 }
57 if (config->bundleName != nullptr) {
58 free(static_cast<void *>(const_cast<char *>(config->bundleName)));
59 }
60 if (config->moduleName != nullptr) {
61 free(static_cast<void *>(const_cast<char *>(config->moduleName)));
62 }
63 delete config;
64 config = nullptr;
65 }
66
CreateRandomTransOptions(FuzzedDataProvider & provider)67 OH_RDB_TransOptions *CreateRandomTransOptions(FuzzedDataProvider &provider)
68 {
69 OH_RDB_TransOptions *options = OH_RdbTrans_CreateOptions();
70 if (options == nullptr) {
71 return nullptr;
72 }
73 OH_RDB_TransType type =
74 static_cast<OH_RDB_TransType>(provider.ConsumeIntegralInRange<int>(RDB_TRANS_DEFERRED, RDB_TRANS_BUTT));
75 OH_RdbTransOption_SetType(options, type);
76 return options;
77 }
78
CreateRandomVBucket(FuzzedDataProvider & provider)79 OH_VBucket *CreateRandomVBucket(FuzzedDataProvider &provider)
80 {
81 OH_VBucket *vBucket = OH_Rdb_CreateValuesBucket();
82 if (vBucket == nullptr) {
83 return nullptr;
84 }
85 const int minLen = 1;
86 const int maxLen = 50;
87 size_t len = provider.ConsumeIntegralInRange<size_t>(minLen, maxLen);
88 for (size_t i = 0; i < len; i++) {
89 std::string column = provider.ConsumeRandomLengthString();
90 int64_t value = provider.ConsumeIntegral<int64_t>();
91 vBucket->putInt64(vBucket, column.c_str(), value);
92 }
93 return vBucket;
94 }
95
96 std::vector<OH_VBucket*> g_randomVBuckets;
CreateRandomVBuckets(FuzzedDataProvider & provider)97 OH_Data_VBuckets *CreateRandomVBuckets(FuzzedDataProvider &provider)
98 {
99 const int minRowCount = 1;
100 const int maxRowCount = 5;
101 g_randomVBuckets.clear();
102 size_t rowCount = provider.ConsumeIntegralInRange<size_t>(minRowCount, maxRowCount);
103 OH_Data_VBuckets *list = OH_VBuckets_Create();
104 for (size_t i = 0; i < rowCount; i++) {
105 OH_VBucket *valueBucket = CreateRandomVBucket(provider);
106 g_randomVBuckets.push_back(valueBucket);
107 OH_VBuckets_PutRow(list, valueBucket);
108 }
109 return list;
110 }
111
DeleteCapiValueBuckets(OH_Data_VBuckets * rows)112 void DeleteCapiValueBuckets(OH_Data_VBuckets *rows)
113 {
114 OH_VBuckets_Destroy(rows);
115 for (auto row : g_randomVBuckets) {
116 if (row != nullptr) {
117 row->destroy(row);
118 }
119 }
120 g_randomVBuckets.clear();
121 }
122
CreateTransVObject(FuzzedDataProvider & provider)123 OH_VObject *CreateTransVObject(FuzzedDataProvider &provider)
124 {
125 OH_VObject *valueObject = OH_Rdb_CreateValueObject();
126 if (valueObject == nullptr) {
127 return nullptr;
128 }
129 std::string value = provider.ConsumeRandomLengthString();
130 valueObject->putText(valueObject, value.c_str());
131 return valueObject;
132 }
133
GetCapiTransPredicates(FuzzedDataProvider & provider,std::string table)134 OH_Predicates* GetCapiTransPredicates(FuzzedDataProvider &provider, std::string table)
135 {
136 OH_Predicates *predicates = OH_Rdb_CreatePredicates(table.c_str());
137 if (predicates == nullptr) {
138 return nullptr;
139 }
140 std::string value = provider.ConsumeRandomLengthString();
141 OH_VObject *valueObject = CreateTransVObject(provider);
142 if (valueObject == nullptr) {
143 predicates->destroy(predicates);
144 return nullptr;
145 }
146 predicates->equalTo(predicates, value.c_str(), valueObject);
147 valueObject->destroy(valueObject);
148 return predicates;
149 }
150
DeleteCapiTransPredicates(OH_Predicates * predicates)151 void DeleteCapiTransPredicates(OH_Predicates *predicates)
152 {
153 if (predicates == nullptr) {
154 return;
155 }
156 predicates->destroy(predicates);
157 }
158
TransactionFuzzTest(FuzzedDataProvider & provider)159 void TransactionFuzzTest(FuzzedDataProvider &provider)
160 {
161 static bool runEndFlag = false;
162 OH_Rdb_Config *config = CreateRandomConfig(provider);
163 int errCode;
164 OH_Rdb_Store *store = OH_Rdb_GetOrOpen(config, &errCode);
165 OH_RDB_TransOptions *options = CreateRandomTransOptions(provider);
166 OH_Rdb_Transaction *trans = nullptr;
167 OH_Rdb_CreateTransaction(store, options, &trans);
168 OH_RdbTrans_Commit(trans);
169 OH_RdbTrans_Rollback(trans);
170 std::string table = provider.ConsumeRandomLengthString();
171 int64_t rowId = 0;
172 OH_VBucket *valueBucket = CreateRandomVBucket(provider);
173 OH_RdbTrans_Insert(trans, table.c_str(), valueBucket, &rowId);
174 OH_Data_VBuckets *list = CreateRandomVBuckets(provider);
175 std::string batchTable = provider.ConsumeRandomLengthString();
176 int64_t changes;
177 Rdb_ConflictResolution resolution = static_cast<Rdb_ConflictResolution>(
178 provider.ConsumeIntegralInRange<int>(RDB_CONFLICT_NONE, RDB_CONFLICT_REPLACE));
179 OH_RdbTrans_BatchInsert(trans, batchTable.c_str(), list, resolution, &changes);
180 OH_RdbTrans_InsertWithConflictResolution(trans, table.c_str(), valueBucket, resolution, &rowId);
181 OH_Predicates *predicate = GetCapiTransPredicates(provider, table);
182 OH_RdbTrans_UpdateWithConflictResolution(trans, valueBucket, predicate, resolution, &rowId);
183 DeleteCapiTransPredicates(predicate);
184 DeleteCapiValueBuckets(list);
185 OH_Rdb_CloseStore(store);
186 ReleaseConfig(config);
187 OH_RdbTrans_DestroyOptions(options);
188 if (valueBucket != nullptr) {
189 valueBucket->destroy(valueBucket);
190 }
191 OH_RdbTrans_Destroy(trans);
192 if (!runEndFlag) {
193 runEndFlag = true;
194 std::cout << "TransactionFuzzTest end" << std::endl;
195 }
196 }
197
198 /* Fuzzer entry point */
LLVMFuzzerTestOneInput(const uint8_t * data,size_t size)199 extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
200 {
201 // Run your code on data
202 FuzzedDataProvider provider(data, size);
203 TransactionFuzzTest(provider);
204 return 0;
205 }
206