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 #include "relationalstore_fuzzer.h"
16
17 #include <fuzzer/FuzzedDataProvider.h>
18 #include <iostream>
19 #include <sys/stat.h>
20
21 #include "grd_api_manager.h"
22 #include "rdb_errno.h"
23 #include "relational_store.h"
24 #include "relational_store_error_code.h"
25 #include "relational_store_impl.h"
26 #include "accesstoken_kit.h"
27
28 static constexpr const char *RDB_TEST_PATH = "/data/storage/el2/database/com.ohos.example.distributedndk/entry/";
29
30 using namespace OHOS::NativeRdb;
31 using namespace OHOS::RdbNdk;
32 using namespace OHOS::Security::AccessToken;
33
CreateAndSetCryptoParam(FuzzedDataProvider & provider,OH_Rdb_ConfigV2 * config)34 void CreateAndSetCryptoParam(FuzzedDataProvider &provider, OH_Rdb_ConfigV2 *config)
35 {
36 if (config == nullptr) {
37 return;
38 }
39 OH_Rdb_CryptoParam *param = OH_Rdb_CreateCryptoParam();
40 int32_t length = provider.ConsumeIntegral<int32_t>();
41 std::vector<uint8_t> key = provider.ConsumeBytes<uint8_t>(length);
42 int64_t iterator = provider.ConsumeIntegral<int32_t>();
43 int32_t algo = provider.ConsumeIntegral<int32_t>();
44 int64_t size = provider.ConsumeIntegral<int32_t>();
45
46 OH_Crypto_SetEncryptionKey(param, key.data(), key.size());
47 OH_Crypto_SetIteration(param, iterator);
48 OH_Crypto_SetEncryptionAlgo(param, algo);
49 OH_Crypto_SetHmacAlgo(param, algo);
50 OH_Crypto_SetKdfAlgo(param, algo);
51 OH_Crypto_SetCryptoPageSize(param, size);
52 OH_Rdb_SetCryptoParam(config, param);
53 if (param != nullptr) {
54 OH_Rdb_DestroyCryptoParam(param);
55 }
56 }
57
58 constexpr int RDB_CONFIG_PLUGINS_MAX = 16;
CreateAndSetPlugins(FuzzedDataProvider & provider,OH_Rdb_ConfigV2 * config)59 void CreateAndSetPlugins(FuzzedDataProvider &provider, OH_Rdb_ConfigV2 *config)
60 {
61 uint32_t count = provider.ConsumeIntegralInRange(0, RDB_CONFIG_PLUGINS_MAX);
62 std::vector<std::string> plugins;
63 for (uint32_t i = 0; i < count; i++) {
64 plugins.push_back(provider.ConsumeRandomLengthString());
65 }
66 const char *arr[RDB_CONFIG_PLUGINS_MAX] = {nullptr};
67 for (size_t i = 0; i < count; ++i) {
68 arr[i] = plugins[i].c_str();
69 }
70 OH_Rdb_SetPlugins(config, arr, count);
71 }
72
AppendApi20ConfigV2(FuzzedDataProvider & provider,struct OH_Rdb_ConfigV2 * configV2)73 void AppendApi20ConfigV2(FuzzedDataProvider &provider, struct OH_Rdb_ConfigV2 *configV2)
74 {
75 if (configV2 == nullptr) {
76 return;
77 }
78 bool readOnly = provider.ConsumeBool();
79 OH_Rdb_SetReadOnly(configV2, readOnly);
80 std::string customDir = provider.ConsumeRandomLengthString();
81 OH_Rdb_SetCustomDir(configV2, customDir.c_str());
82 CreateAndSetPlugins(provider, configV2);
83 CreateAndSetCryptoParam(provider, configV2);
84 }
85
CreateOHRdbConfigV2(FuzzedDataProvider & provider)86 struct OH_Rdb_ConfigV2 *CreateOHRdbConfigV2(FuzzedDataProvider &provider)
87 {
88 struct OH_Rdb_ConfigV2 *configV2 = OH_Rdb_CreateConfig();
89 if (configV2 == nullptr) {
90 return nullptr;
91 }
92 std::string databaseDir = provider.ConsumeRandomLengthString();
93 OH_Rdb_SetDatabaseDir(configV2, databaseDir.c_str());
94 std::string storeName = provider.ConsumeRandomLengthString();
95 OH_Rdb_SetStoreName(configV2, storeName.c_str());
96 std::string bundleName = provider.ConsumeRandomLengthString();
97 OH_Rdb_SetBundleName(configV2, bundleName.c_str());
98 std::string bmoduleName = provider.ConsumeRandomLengthString();
99 OH_Rdb_SetModuleName(configV2, bmoduleName.c_str());
100 bool isEncrypted = provider.ConsumeBool();
101 OH_Rdb_SetEncrypted(configV2, isEncrypted);
102 int securityLevel = provider.ConsumeIntegral<int>();
103 OH_Rdb_SetSecurityLevel(configV2, securityLevel);
104 int area = provider.ConsumeIntegral<int>();
105 OH_Rdb_SetArea(configV2, area);
106 int dbType = provider.ConsumeIntegral<int>();
107 OH_Rdb_SetDbType(configV2, dbType);
108
109 Rdb_Tokenizer tokenizer =
110 static_cast<Rdb_Tokenizer>(provider.ConsumeIntegralInRange<int>(RDB_NONE_TOKENIZER, RDB_CUSTOM_TOKENIZER));
111 bool isSupported = false;
112 OH_Rdb_IsTokenizerSupported(tokenizer, &isSupported);
113 {
114 Rdb_Tokenizer tokenizer =
115 static_cast<Rdb_Tokenizer>(provider.ConsumeIntegralInRange<int>(RDB_NONE_TOKENIZER, RDB_CUSTOM_TOKENIZER));
116 OH_Rdb_SetTokenizer(configV2, tokenizer);
117 }
118 bool isPersistent = provider.ConsumeBool();
119 OH_Rdb_SetPersistent(configV2, isPersistent);
120 int typeCount = 0;
121 OH_Rdb_GetSupportedDbType(&typeCount);
122 return configV2;
123 }
124
CreateOHVObject(FuzzedDataProvider & provider)125 OH_VObject *CreateOHVObject(FuzzedDataProvider &provider)
126 {
127 OH_VObject *valueObject = OH_Rdb_CreateValueObject();
128 if (valueObject == nullptr) {
129 return nullptr;
130 }
131 std::string value = provider.ConsumeRandomLengthString();
132 valueObject->putText(valueObject, value.c_str());
133 return valueObject;
134 }
135
CreateOHVBucket(FuzzedDataProvider & provider)136 OH_VBucket *CreateOHVBucket(FuzzedDataProvider &provider)
137 {
138 OH_VBucket *valueBucket = OH_Rdb_CreateValuesBucket();
139 if (valueBucket == nullptr) {
140 return nullptr;
141 }
142 {
143 std::string key = provider.ConsumeRandomLengthString();
144 int64_t value = provider.ConsumeIntegral<int64_t>();
145 valueBucket->putInt64(valueBucket, key.c_str(), value);
146 }
147 {
148 std::string key = provider.ConsumeRandomLengthString();
149 std::string value = provider.ConsumeRandomLengthString();
150 valueBucket->putText(valueBucket, key.c_str(), value.c_str());
151 }
152 {
153 std::string key = provider.ConsumeRandomLengthString();
154 float value = provider.ConsumeFloatingPoint<float>();
155 valueBucket->putReal(valueBucket, key.c_str(), value);
156 }
157 {
158 std::string key = provider.ConsumeRandomLengthString();
159 const int minBlobSize = 1;
160 const int maxBlobSize = 50;
161 size_t blobSize = provider.ConsumeIntegralInRange<size_t>(minBlobSize, maxBlobSize);
162 std::vector<uint8_t> blobData = provider.ConsumeBytes<uint8_t>(blobSize);
163 valueBucket->putBlob(valueBucket, key.c_str(), blobData.data(), blobData.size());
164 }
165 return valueBucket;
166 }
167
RelationalStoreCAPIFuzzTest(FuzzedDataProvider & provider)168 void RelationalStoreCAPIFuzzTest(FuzzedDataProvider &provider)
169 {
170 struct OH_Rdb_ConfigV2 *configV2 = CreateOHRdbConfigV2(provider);
171 if (configV2 == nullptr) {
172 return;
173 }
174 OH_VObject *valueObject = CreateOHVObject(provider);
175 if (valueObject == nullptr) {
176 return;
177 }
178 std::string table = provider.ConsumeRandomLengthString();
179 OH_Predicates *predicates = OH_Rdb_CreatePredicates(table.c_str());
180 if (predicates == nullptr) {
181 return;
182 }
183 {
184 std::string value = provider.ConsumeRandomLengthString();
185 predicates->equalTo(predicates, value.c_str(), valueObject);
186 }
187
188 OH_VBucket *valueBucket = CreateOHVBucket(provider);
189 if (valueBucket == nullptr) {
190 return;
191 }
192
193 int errCode = 0;
194 static OH_Rdb_Store *OHRdbStore = OH_Rdb_CreateOrOpen(configV2, &errCode);
195 {
196 table = provider.ConsumeRandomLengthString();
197 OH_Rdb_Insert(OHRdbStore, table.c_str(), valueBucket);
198 }
199 OH_Data_VBuckets *list = OH_VBuckets_Create();
200 OH_VBuckets_PutRow(list, valueBucket);
201 {
202 table = provider.ConsumeRandomLengthString();
203 Rdb_ConflictResolution resolution = static_cast<Rdb_ConflictResolution>(
204 provider.ConsumeIntegralInRange<int>(RDB_CONFLICT_NONE, RDB_CONFLICT_REPLACE));
205 int64_t changes = 0;
206 OH_Rdb_BatchInsert(OHRdbStore, table.c_str(), list, resolution, &changes);
207 }
208 OH_Rdb_Update(OHRdbStore, valueBucket, predicates);
209 valueBucket->destroy(valueBucket);
210 predicates->destroy(predicates);
211 valueObject->destroy(valueObject);
212 OH_VBuckets_Destroy(list);
213 OH_Rdb_CloseStore(OHRdbStore);
214 OH_Rdb_DeleteStoreV2(configV2);
215 OH_Rdb_DestroyConfig(configV2);
216 }
217
RelationalConfigV2Capi20FuzzTest(FuzzedDataProvider & provider)218 void RelationalConfigV2Capi20FuzzTest(FuzzedDataProvider &provider)
219 {
220 static bool runEndFlag = false;
221 struct OH_Rdb_ConfigV2 *configV2 = CreateOHRdbConfigV2(provider);
222 if (configV2 == nullptr) {
223 return;
224 }
225 AppendApi20ConfigV2(provider, configV2);
226 OH_Rdb_DestroyConfig(configV2);
227 if (!runEndFlag) {
228 runEndFlag = true;
229 std::cout << "RelationalConfigV2Capi20FuzzTest end" << std::endl;
230 }
231 }
232
233 OH_Rdb_ConfigV2* g_normalConfig = nullptr;
MockHap(void)234 void MockHap(void)
235 {
236 HapInfoParams info = {
237 .userID = 100,
238 .bundleName = "com.example.distributed",
239 .instIndex = 0,
240 .appIDDesc = "com.example.distributed"
241 };
242 PermissionDef infoManagerTestPermDef = {
243 .permissionName = "ohos.permission.test",
244 .bundleName = "com.example.distributed",
245 .grantMode = 1,
246 .availableLevel = APL_NORMAL,
247 .label = "label",
248 .labelId = 1,
249 .description = "open the door",
250 .descriptionId = 1
251 };
252 PermissionStateFull infoManagerTestState = {
253 .permissionName = "ohos.permission.test",
254 .isGeneral = true,
255 .resDeviceID = { "local" },
256 .grantStatus = { PermissionState::PERMISSION_GRANTED },
257 .grantFlags = { 1 }
258 };
259 HapPolicyParams policy = {
260 .apl = APL_NORMAL,
261 .domain = "test.domain",
262 .permList = { infoManagerTestPermDef },
263 .permStateList = { infoManagerTestState }
264 };
265 AccessTokenKit::AllocHapToken(info, policy);
266 }
267
GetFuzzerNormalStore()268 OH_Rdb_Store *GetFuzzerNormalStore()
269 {
270 MockHap();
271 // 0770 is permission
272 mkdir(RDB_TEST_PATH, 0770);
273 g_normalConfig = OH_Rdb_CreateConfig();
274 OH_Rdb_SetDatabaseDir(g_normalConfig, RDB_TEST_PATH);
275 OH_Rdb_SetStoreName(g_normalConfig, "rdb_store_test.db");
276 OH_Rdb_SetBundleName(g_normalConfig, "com.ohos.example.distributedndk");
277 OH_Rdb_SetEncrypted(g_normalConfig, false);
278 OH_Rdb_SetSecurityLevel(g_normalConfig, OH_Rdb_SecurityLevel::S1);
279 OH_Rdb_SetArea(g_normalConfig, RDB_SECURITY_AREA_EL1);
280 int errCode = 0;
281 OH_Rdb_Store *store = OH_Rdb_CreateOrOpen(g_normalConfig, &errCode);
282 return store;
283 }
284
DeleteFuzzerNormalStroe(OH_Rdb_Store * store)285 void DeleteFuzzerNormalStroe(OH_Rdb_Store *store)
286 {
287 if (store != nullptr) {
288 delete store;
289 }
290 OH_Rdb_DeleteStoreV2(g_normalConfig);
291 OH_Rdb_DestroyConfig(g_normalConfig);
292 g_normalConfig = nullptr;
293 }
294
295
InitFuzzerNormalStore(OH_Rdb_Store * store)296 void InitFuzzerNormalStore(OH_Rdb_Store *store)
297 {
298 if (store == nullptr) {
299 return;
300 }
301 char createTableSql[] = "CREATE TABLE test (id INTEGER PRIMARY KEY AUTOINCREMENT, data1 TEXT, data2 INTEGER, "
302 "data3 FLOAT, data4 BLOB, data5 TEXT);";
303 OH_Rdb_Execute(store, createTableSql);
304 }
305
GetFuzzerNormalValuesBucket()306 OH_VBucket* GetFuzzerNormalValuesBucket()
307 {
308 OH_VBucket *valueBucket = OH_Rdb_CreateValuesBucket();
309 valueBucket->putInt64(valueBucket, "id", 1);
310 valueBucket->putText(valueBucket, "data1", "zhangSan");
311 // 12800 stub number
312 valueBucket->putInt64(valueBucket, "data2", 12800);
313 // 100.1 stub number
314 valueBucket->putReal(valueBucket, "data3", 100.1);
315 valueBucket->putText(valueBucket, "data5", "ABCDEFG");
316 return valueBucket;
317 }
318
DeleteFuzzerNormalValuesBucket(OH_VBucket * valueBucket)319 void DeleteFuzzerNormalValuesBucket(OH_VBucket *valueBucket)
320 {
321 if (valueBucket == nullptr) {
322 return;
323 }
324 valueBucket->destroy(valueBucket);
325 }
326
GetCapi20Predicates(FuzzedDataProvider & provider,std::string table)327 OH_Predicates* GetCapi20Predicates(FuzzedDataProvider &provider, std::string table)
328 {
329 OH_Predicates *predicates = OH_Rdb_CreatePredicates(table.c_str());
330 if (predicates == nullptr) {
331 return nullptr;
332 }
333 std::string value = provider.ConsumeRandomLengthString();
334 OH_VObject *valueObject = CreateOHVObject(provider);
335 if (valueObject == nullptr) {
336 predicates->destroy(predicates);
337 return nullptr;
338 }
339 predicates->equalTo(predicates, value.c_str(), valueObject);
340 valueObject->destroy(valueObject);
341 return predicates;
342 }
343
DeleteCapi20Predicates(OH_Predicates * predicates)344 void DeleteCapi20Predicates(OH_Predicates *predicates)
345 {
346 if (predicates != nullptr) {
347 return;
348 }
349 predicates->destroy(predicates);
350 }
351
352
RelationalStoreCapi20FuzzTest(FuzzedDataProvider & provider)353 void RelationalStoreCapi20FuzzTest(FuzzedDataProvider &provider)
354 {
355 static bool runEndFlag = false;
356 int64_t rowId;
357 std::string table = "test";
358 Rdb_ConflictResolution resolution = static_cast<Rdb_ConflictResolution>(
359 provider.ConsumeIntegralInRange<int>(RDB_CONFLICT_NONE, RDB_CONFLICT_REPLACE));
360
361 OH_Rdb_Store *store = GetFuzzerNormalStore();
362 OH_VBucket *valueBucket = GetFuzzerNormalValuesBucket();
363 OH_Predicates *predicates = GetCapi20Predicates(provider, table);
364 do {
365 if (store == nullptr || valueBucket == nullptr || predicates == nullptr) {
366 break;
367 }
368 OH_Rdb_InsertWithConflictResolution(store, table.c_str(), valueBucket, resolution, &rowId);
369 OH_Rdb_UpdateWithConflictResolution(store, valueBucket, predicates, resolution, &rowId);
370 if (!runEndFlag) {
371 runEndFlag = true;
372 std::cout << "RelationalStoreCapi20FuzzTest end" << std::endl;
373 }
374 } while (0);
375
376 DeleteCapi20Predicates(predicates);
377 DeleteFuzzerNormalValuesBucket(valueBucket);
378 DeleteFuzzerNormalStroe(store);
379 }
380
RelationalStoreAttatchFuzzTest(FuzzedDataProvider & provider)381 void RelationalStoreAttatchFuzzTest(FuzzedDataProvider &provider)
382 {
383 static bool runEndFlag = false;
384 OH_Rdb_Store *store = GetFuzzerNormalStore();
385 OH_Rdb_ConfigV2 *attachConfig = OH_Rdb_CreateConfig();
386 int64_t waitTime = provider.ConsumeIntegral<int32_t>();
387 do {
388 if (store == nullptr || attachConfig == nullptr) {
389 break;
390 }
391 OH_Rdb_SetDatabaseDir(attachConfig, RDB_TEST_PATH);
392 OH_Rdb_SetStoreName(attachConfig, "rdb_attach_store_test.db");
393 OH_Rdb_SetBundleName(attachConfig, "com.ohos.example.distributedndk");
394 OH_Rdb_SetEncrypted(attachConfig, false);
395 OH_Rdb_SetSecurityLevel(attachConfig, OH_Rdb_SecurityLevel::S1);
396 OH_Rdb_SetArea(attachConfig, RDB_SECURITY_AREA_EL1);
397
398 size_t attachedNumber = 0;
399 OH_Rdb_Attach(store, attachConfig, "attach_test", waitTime, &attachedNumber);
400 OH_Rdb_Detach(store, "attach_test", waitTime, &attachedNumber);
401 if (!runEndFlag) {
402 runEndFlag = true;
403 std::cout << "RelationalStoreAttatchFuzzTest end" << std::endl;
404 }
405 } while (0);
406
407 OH_Rdb_DestroyConfig(attachConfig);
408 DeleteFuzzerNormalStroe(store);
409 }
410
411 /* Fuzzer entry point */
LLVMFuzzerTestOneInput(const uint8_t * data,size_t size)412 extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
413 {
414 /* Run your code on data */
415 FuzzedDataProvider provider(data, size);
416
417 RelationalStoreCAPIFuzzTest(provider);
418
419 // Test OH_Rdb_SetCryptoParam
420 RelationalConfigV2Capi20FuzzTest(provider);
421
422 // Test OH_Rdb_InsertWithConflictResolution and OH_Rdb_UpdateWithConflictResolution
423 RelationalStoreCapi20FuzzTest(provider);
424
425 // Test OH_Rdb_Attach and OH_Rdb_Detach
426 RelationalStoreAttatchFuzzTest(provider);
427 return 0;
428 }
429