• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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