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 "kvutil_fuzzer.h"
17
18 #include <string>
19 #include <sys/stat.h>
20 #include <vector>
21 #include "distributed_kv_data_manager.h"
22 #include "fuzzer/FuzzedDataProvider.h"
23 #include "datashare_predicates.h"
24 #include "datashare_values_bucket.h"
25 #include "store_errno.h"
26 #include "kv_utils.h"
27
28 using namespace OHOS;
29 using namespace OHOS::DistributedKv;
30 using namespace OHOS::DataShare;
31 namespace OHOS {
32 using ValueType = std::variant<std::monostate, int64_t, double, std::string, bool, std::vector<uint8_t>>;
33 static std::shared_ptr<SingleKvStore> singleKvStore_ = nullptr;
34 static constexpr const char *KEY = "key";
35 static constexpr const char *VALUE = "value";
36 static constexpr const char *PREFIX = "test_";
37 enum DataType {
38 STRING = 1,
39 INT64,
40 BOOL,
41 DOUBLE,
42 VECTOR_INT64,
43 };
44
SetUpTestCase(void)45 void SetUpTestCase(void)
46 {
47 DistributedKvDataManager manager;
48 Options options = {
49 .createIfMissing = true,
50 .encrypt = false,
51 .autoSync = true,
52 .securityLevel = S1,
53 .kvStoreType = KvStoreType::SINGLE_VERSION
54 };
55 options.area = EL1;
56 AppId appId = { "kvstorefuzzertest" };
57 options.baseDir = std::string("/data/service/el1/public/database/") + appId.appId;
58 /* define kvstore(database) name. */
59 StoreId storeId = { "fuzzer_single" };
60 mkdir(options.baseDir.c_str(), (S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH));
61 /* [create and] open and initialize kvstore instance. */
62 manager.GetSingleKvStore(options, appId, storeId, singleKvStore_);
63 }
64
TearDown(void)65 void TearDown(void)
66 {
67 (void)remove("/data/service/el1/public/database/kvutilfuzzertest/key");
68 (void)remove("/data/service/el1/public/database/kvutilfuzzertest/kvdb");
69 (void)remove("/data/service/el1/public/database/kvutilfuzzertest");
70 }
71
ToResultSetBridgeFuzz(FuzzedDataProvider & provider)72 void ToResultSetBridgeFuzz(FuzzedDataProvider &provider)
73 {
74 std::string skey;
75 std::string svalue;
76 Entry entry;
77 std::vector<Entry> entries;
78 std::vector<Key> keys;
79 int sum = provider.ConsumeIntegralInRange<size_t>(0, 10);
80 for (size_t i = 0; i < sum; i++) {
81 skey = provider.ConsumeRandomLengthString();
82 svalue = provider.ConsumeRandomLengthString();
83 entry.key = {PREFIX + skey};
84 entry.value = {PREFIX + svalue};
85 entries.push_back(entry);
86 keys.push_back(entry.key);
87 }
88 singleKvStore_->PutBatch(entries);
89 std::shared_ptr<KvStoreResultSet> resultSet = nullptr;
90 DataSharePredicates predicates;
91 predicates.KeyPrefix("test");
92 DataQuery query;
93 auto status = KvUtils::ToQuery(predicates, query);
94 if (status == Status::SUCCESS) {
95 status = singleKvStore_->GetResultSet(query, resultSet);
96 }
97 KvUtils::ToResultSetBridge(resultSet);
98 singleKvStore_->DeleteBatch(keys);
99 }
100
ToEntryFuzz(FuzzedDataProvider & provider)101 void ToEntryFuzz(FuzzedDataProvider &provider)
102 {
103 DataShareValuesBucket bucket {};
104 if (provider.ConsumeBool()) {
105 bucket.Put(KEY, provider.ConsumeRandomLengthString());
106 bucket.Put(VALUE, provider.ConsumeRandomLengthString());
107 }
108 auto entry = KvUtils::ToEntry(bucket);
109 }
110
CreateData(int32_t type,FuzzedDataProvider & provider)111 ValueType CreateData(int32_t type, FuzzedDataProvider &provider)
112 {
113 ValueType data;
114 switch (type) {
115 case DataType::STRING:
116 data = provider.ConsumeRandomLengthString();
117 break;
118 case DataType::INT64:
119 data = provider.ConsumeIntegral<int64_t>();
120 break;
121 case DataType::BOOL:
122 data = provider.ConsumeBool();
123 break;
124 case DataType::DOUBLE:
125 data = provider.ConsumeFloatingPoint<double>();
126 break;
127 case DataType::VECTOR_INT64:
128 data = provider.ConsumeRemainingBytes<uint8_t>();
129 break;
130 default:
131 data = {};
132 break;
133 }
134 return data;
135 }
136
ToEntriesFuzz(FuzzedDataProvider & provider)137 void ToEntriesFuzz(FuzzedDataProvider &provider)
138 {
139 std::vector<DataShareValuesBucket> buckets;
140 const uint8_t bucketCount = provider.ConsumeIntegralInRange<uint8_t>(1, 10);
141 DataShareValuesBucket bucket;
142 ValueType key;
143 ValueType value;
144 for (int i = 1; i < bucketCount; ++i) {
145 auto keyType = provider.ConsumeIntegralInRange(1, 5);
146 auto valueType = provider.ConsumeIntegralInRange(1, 5);
147 key = CreateData(keyType, provider);
148 value = CreateData(valueType, provider);
149 bucket.Put(KEY, key);
150 bucket.Put(VALUE, value);
151 buckets.push_back(std::move(bucket));
152 }
153 auto entry = KvUtils::ToEntries(buckets);
154 }
155
GetKeysFuzz(FuzzedDataProvider & provider)156 void GetKeysFuzz(FuzzedDataProvider &provider)
157 {
158 std::vector<std::string> keys;
159 keys.push_back(provider.ConsumeRandomLengthString());
160 keys.push_back(provider.ConsumeRandomLengthString());
161 keys.push_back(provider.ConsumeRandomLengthString());
162 DataSharePredicates predicates;
163 predicates.InKeys(keys);
164 std::vector<Key> kvKeys;
165 KvUtils::GetKeys(predicates, kvKeys);
166 }
167 } // namespace OHOS
168
169 /* Fuzzer entry point */
LLVMFuzzerTestOneInput(const uint8_t * data,size_t size)170 extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
171 {
172 /* Run your code on data */
173 FuzzedDataProvider provider(data, size);
174 OHOS::SetUpTestCase();
175 OHOS::ToResultSetBridgeFuzz(provider);
176 OHOS::ToEntryFuzz(provider);
177 OHOS::ToEntriesFuzz(provider);
178 OHOS::GetKeysFuzz(provider);
179 OHOS::TearDown();
180 return 0;
181 }