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 "transdb_fuzzer.h"
16
17 #include <fuzzer/FuzzedDataProvider.h>
18 #include <rdb_helper.h>
19 #include <rdb_store.h>
20 #include <rdb_store_config.h>
21 #include <securec.h>
22 #include <values_bucket.h>
23
24 #include <memory>
25
26 #include "connection_pool.h"
27 #include "trans_db.h"
28
29 using namespace OHOS;
30 using namespace OHOS::NativeRdb;
31 namespace OHOS {
32
33 static constexpr const char *CREATE_TABLE = "CREATE TABLE IF NOT EXISTS TEST (id INT PRIMARY KEY, name TEXT, "
34 "extend BLOB, code REAL, years UNLIMITED INT, attachment ASSET, "
35 "attachments ASSETS)";
36 static constexpr const char *DROP_TABLE = "DROP TABLE IF EXISTS TEST";
37 static constexpr const char *TABLE_NAME = "TEST";
38 static const int MIN_ROWS_SIZE = 1;
39 static const int MAX_ROWS_SIZE = 50;
40
FillDataToValuesBucket(FuzzedDataProvider & provider,ValuesBucket & value)41 void FillDataToValuesBucket(FuzzedDataProvider &provider, ValuesBucket &value)
42 {
43 std::string valName = provider.ConsumeRandomLengthString();
44 int valAge = provider.ConsumeIntegral<int>();
45 double valSalary = provider.ConsumeFloatingPoint<double>();
46
47 value.PutString("name", valName);
48 value.PutInt("age", valAge);
49 value.PutDouble("salary", valSalary);
50 }
51
FillDataToValuesBuckets(FuzzedDataProvider & provider,ValuesBuckets & values)52 void FillDataToValuesBuckets(FuzzedDataProvider &provider, ValuesBuckets &values)
53 {
54 uint32_t loopTimes = provider.ConsumeIntegralInRange<uint32_t>(MIN_ROWS_SIZE, MAX_ROWS_SIZE);
55 for (uint32_t i = 0; i < loopTimes; i++) {
56 ValuesBucket value;
57 FillDataToValuesBucket(provider, value);
58 values.Put(value);
59 }
60 }
61
TransDbExecuteFuzzTest(std::shared_ptr<RdbStore> transDB,FuzzedDataProvider & provider)62 void TransDbExecuteFuzzTest(std::shared_ptr<RdbStore> transDB, FuzzedDataProvider &provider)
63 {
64 if (transDB == nullptr) {
65 return;
66 }
67 transDB->Execute(DROP_TABLE);
68 transDB->Execute(CREATE_TABLE);
69 std::string sql = provider.ConsumeRandomLengthString();
70 transDB->Execute(sql);
71 }
72
GetConflictResolution(FuzzedDataProvider & provider)73 ConflictResolution GetConflictResolution(FuzzedDataProvider &provider)
74 {
75 int min = static_cast<int>(ConflictResolution::ON_CONFLICT_NONE);
76 int max = static_cast<int>(ConflictResolution::ON_CONFLICT_REPLACE);
77 int enumInt = provider.ConsumeIntegralInRange<int>(min, max);
78 ConflictResolution resolution = static_cast<ConflictResolution>(enumInt);
79 return resolution;
80 }
81
TransDbInsertFuzzTest(std::shared_ptr<RdbStore> transDB,FuzzedDataProvider & provider)82 void TransDbInsertFuzzTest(std::shared_ptr<RdbStore> transDB, FuzzedDataProvider &provider)
83 {
84 if (transDB == nullptr) {
85 return;
86 }
87 ValuesBucket value;
88 FillDataToValuesBucket(provider, value);
89
90 {
91 ConflictResolution resolution = GetConflictResolution(provider);
92 transDB->Insert(TABLE_NAME, value, resolution);
93 }
94
95 ValuesBuckets rows;
96 FillDataToValuesBuckets(provider, rows);
97 transDB->BatchInsert(TABLE_NAME, rows);
98
99 {
100 ConflictResolution resolution = GetConflictResolution(provider);
101 transDB->BatchInsert(TABLE_NAME, rows, resolution);
102 }
103 }
104
TransDbFuzzTest(FuzzedDataProvider & provider)105 void TransDbFuzzTest(FuzzedDataProvider &provider)
106 {
107 std::string path = provider.ConsumeRandomLengthString();
108 RdbStoreConfig config(path);
109 config.SetHaMode(provider.ConsumeIntegral<int32_t>());
110 int errCode = 0;
111 std::shared_ptr<ConnectionPool> connPool = ConnectionPool::Create(config, errCode);
112 if (connPool == nullptr) {
113 return;
114 }
115 auto [err, conn] = connPool->CreateTransConn();
116 if (err != E_OK || conn == nullptr) {
117 return;
118 }
119 std::shared_ptr<RdbStore> transDB = std::make_shared<TransDB>(conn, config.GetName());
120 if (transDB == nullptr) {
121 return;
122 }
123 TransDbExecuteFuzzTest(transDB, provider);
124 TransDbInsertFuzzTest(transDB, provider);
125 }
126
127 } // namespace OHOS
128
LLVMFuzzerTestOneInput(const uint8_t * data,size_t size)129 extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
130 {
131 FuzzedDataProvider provider(data, size);
132 OHOS::TransDbFuzzTest(provider);
133 return 0;
134 }
135