1 /*
2  * Copyright (c) 2022 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 "singlekvstore_fuzzer.h"
17 
18 #include <string>
19 #include <sys/stat.h>
20 #include <vector>
21 
22 #include "distributed_kv_data_manager.h"
23 #include "store_errno.h"
24 
25 using namespace OHOS;
26 using namespace OHOS::DistributedKv;
27 
28 namespace OHOS {
29 static std::shared_ptr<SingleKvStore> singleKvStore_ = nullptr;
30 
31 class DeviceObserverTestImpl : public KvStoreObserver {
32 public:
33     DeviceObserverTestImpl();
~DeviceObserverTestImpl()34     ~DeviceObserverTestImpl()
35     {
36     }
37     DeviceObserverTestImpl(const DeviceObserverTestImpl &) = delete;
38     DeviceObserverTestImpl &operator=(const DeviceObserverTestImpl &) = delete;
39     DeviceObserverTestImpl(DeviceObserverTestImpl &&) = delete;
40     DeviceObserverTestImpl &operator=(DeviceObserverTestImpl &&) = delete;
41 
42     void OnChange(const ChangeNotification &changeNotification);
43 };
44 
OnChange(const ChangeNotification & changeNotification)45 void DeviceObserverTestImpl::OnChange(const ChangeNotification &changeNotification)
46 {
47 }
48 
DeviceObserverTestImpl()49 DeviceObserverTestImpl::DeviceObserverTestImpl()
50 {
51 }
52 
53 class DeviceSyncCallbackTestImpl : public KvStoreSyncCallback {
54 public:
55     void SyncCompleted(const std::map<std::string, Status> &results);
56 };
57 
SyncCompleted(const std::map<std::string,Status> & results)58 void DeviceSyncCallbackTestImpl::SyncCompleted(const std::map<std::string, Status> &results)
59 {
60 }
61 
SetUpTestCase(void)62 void SetUpTestCase(void)
63 {
64     DistributedKvDataManager manager;
65     Options options = {
66         .createIfMissing = true,
67         .encrypt = false,
68         .autoSync = true,
69         .securityLevel = S1,
70         .kvStoreType = KvStoreType::SINGLE_VERSION
71     };
72     options.area = EL1;
73     AppId appId = { "kvstorefuzzertest" };
74     options.baseDir = std::string("/data/service/el1/public/database/") + appId.appId;
75     /* define kvstore(database) name. */
76     StoreId storeId = { "fuzzer_single" };
77     mkdir(options.baseDir.c_str(), (S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH));
78     /* [create and] open and initialize kvstore instance. */
79     manager.GetSingleKvStore(options, appId, storeId, singleKvStore_);
80 }
81 
TearDown(void)82 void TearDown(void)
83 {
84     (void)remove("/data/service/el1/public/database/singlekvstorefuzzertest/key");
85     (void)remove("/data/service/el1/public/database/singlekvstorefuzzertest/kvdb");
86     (void)remove("/data/service/el1/public/database/singlekvstorefuzzertest");
87 }
88 
PutFuzz(const uint8_t * data,size_t size)89 void PutFuzz(const uint8_t *data, size_t size)
90 {
91     std::string skey(data, data + size);
92     std::string svalue(data, data + size);
93     Key key = { skey };
94     Value val = { svalue };
95     singleKvStore_->Put(key, val);
96     singleKvStore_->Delete(key);
97 }
98 
PutBatchFuzz(const uint8_t * data,size_t size)99 void PutBatchFuzz(const uint8_t *data, size_t size)
100 {
101     std::string skey(data, data + size);
102     std::string svalue(data, data + size);
103     std::vector<Entry> entries;
104     std::vector<Key> keys;
105     Entry entry1;
106     Entry entry2;
107     Entry entry3;
108     entry1.key = { skey + "test_key1" };
109     entry1.value = { svalue + "test_val1" };
110     entry2.key = { skey + "test_key2" };
111     entry2.value = { svalue + "test_val2" };
112     entry3.key = { skey + "test_key3" };
113     entry3.value = { svalue + "test_val3" };
114     entries.push_back(entry1);
115     entries.push_back(entry2);
116     entries.push_back(entry3);
117     keys.push_back(entry1.key);
118     keys.push_back(entry2.key);
119     keys.push_back(entry3.key);
120     singleKvStore_->PutBatch(entries);
121     singleKvStore_->DeleteBatch(keys);
122 }
123 
GetFuzz(const uint8_t * data,size_t size)124 void GetFuzz(const uint8_t *data, size_t size)
125 {
126     std::string skey(data, data + size);
127     std::string svalue(data, data + size);
128     Key key = { skey };
129     Value val = { svalue };
130     Value val1;
131     singleKvStore_->Put(key, val);
132     singleKvStore_->Get(key, val1);
133     singleKvStore_->Delete(key);
134 }
135 
GetEntriesFuzz1(const uint8_t * data,size_t size)136 void GetEntriesFuzz1(const uint8_t *data, size_t size)
137 {
138     std::string prefix(data, data + size);
139     std::string keys = "test_";
140     size_t sum = 10;
141     std::vector<Entry> results;
142     for (size_t i = 0; i < sum; i++) {
143         singleKvStore_->Put(prefix + keys + std::to_string(i), { keys + std::to_string(i) });
144     }
145     singleKvStore_->GetEntries(prefix, results);
146     for (size_t i = 0; i < sum; i++) {
147         singleKvStore_->Delete(prefix + keys + std::to_string(i));
148     }
149 }
150 
GetEntriesFuzz2(const uint8_t * data,size_t size)151 void GetEntriesFuzz2(const uint8_t *data, size_t size)
152 {
153     std::string prefix(data, data + size);
154     DataQuery dataQuery;
155     dataQuery.KeyPrefix(prefix);
156     std::string keys = "test_";
157     std::vector<Entry> entries;
158     size_t sum = 10;
159     for (size_t i = 0; i < sum; i++) {
160         singleKvStore_->Put(prefix + keys + std::to_string(i), keys + std::to_string(i));
161     }
162     singleKvStore_->GetEntries(dataQuery, entries);
163     for (size_t i = 0; i < sum; i++) {
164         singleKvStore_->Delete(prefix + keys + std::to_string(i));
165     }
166 }
167 
SubscribeKvStoreFuzz(const uint8_t * data,size_t size)168 void SubscribeKvStoreFuzz(const uint8_t *data, size_t size)
169 {
170     std::string prefix(data, data + size);
171     DataQuery dataQuery;
172     dataQuery.KeyPrefix(prefix);
173     std::string keys = "test_";
174     size_t sum = 10;
175     for (size_t i = 0; i < sum; i++) {
176         singleKvStore_->Put(prefix + keys + std::to_string(i), keys + std::to_string(i));
177     }
178     auto observer = std::make_shared<DeviceObserverTestImpl>();
179     singleKvStore_->SubscribeKvStore(SubscribeType::SUBSCRIBE_TYPE_ALL, observer);
180     singleKvStore_->UnSubscribeKvStore(SubscribeType::SUBSCRIBE_TYPE_ALL, observer);
181     for (size_t i = 0; i < sum; i++) {
182         singleKvStore_->Delete(prefix + keys + std::to_string(i));
183     }
184 }
185 
SyncCallbackFuzz(const uint8_t * data,size_t size)186 void SyncCallbackFuzz(const uint8_t *data, size_t size)
187 {
188     auto syncCallback = std::make_shared<DeviceSyncCallbackTestImpl>();
189     singleKvStore_->RegisterSyncCallback(syncCallback);
190 
191     std::string prefix(data, data + size);
192     DataQuery dataQuery;
193     dataQuery.KeyPrefix(prefix);
194     std::string keys = "test_";
195     size_t sum = 10;
196     for (size_t i = 0; i < sum; i++) {
197         singleKvStore_->Put(prefix + keys + std::to_string(i), keys + std::to_string(i));
198     }
199 
200     std::map<std::string, Status> results;
201     syncCallback->SyncCompleted(results);
202 
203     for (size_t i = 0; i < sum; i++) {
204         singleKvStore_->Delete(prefix + keys + std::to_string(i));
205     }
206     singleKvStore_->UnRegisterSyncCallback();
207 }
208 
GetResultSetFuzz1(const uint8_t * data,size_t size)209 void GetResultSetFuzz1(const uint8_t *data, size_t size)
210 {
211     std::string prefix(data, data + size);
212     std::string keys = "test_";
213     int position = static_cast<int>(size);
214     std::shared_ptr<KvStoreResultSet> resultSet;
215     size_t sum = 10;
216     for (size_t i = 0; i < sum; i++) {
217         singleKvStore_->Put(prefix + keys + std::to_string(i), keys + std::to_string(i));
218     }
219     auto status = singleKvStore_->GetResultSet(prefix, resultSet);
220     if (status != Status::SUCCESS || resultSet == nullptr) {
221         return;
222     }
223     resultSet->Move(position);
224     resultSet->MoveToPosition(position);
225     Entry entry;
226     resultSet->GetEntry(entry);
227     for (size_t i = 0; i < sum; i++) {
228         singleKvStore_->Delete(prefix + keys + std::to_string(i));
229     }
230 }
231 
GetResultSetFuzz2(const uint8_t * data,size_t size)232 void GetResultSetFuzz2(const uint8_t *data, size_t size)
233 {
234     std::string prefix(data, data + size);
235     DataQuery dataQuery;
236     dataQuery.KeyPrefix(prefix);
237     std::string keys = "test_";
238     std::shared_ptr<KvStoreResultSet> resultSet;
239     size_t sum = 10;
240     for (size_t i = 0; i < sum; i++) {
241         singleKvStore_->Put(prefix + keys + std::to_string(i), keys + std::to_string(i));
242     }
243     singleKvStore_->GetResultSet(dataQuery, resultSet);
244     singleKvStore_->CloseResultSet(resultSet);
245     for (size_t i = 0; i < sum; i++) {
246         singleKvStore_->Delete(prefix + keys + std::to_string(i));
247     }
248 }
249 
GetResultSetFuzz3(const uint8_t * data,size_t size)250 void GetResultSetFuzz3(const uint8_t *data, size_t size)
251 {
252     std::string prefix(data, data + size);
253     DataQuery dataQuery;
254     dataQuery.KeyPrefix(prefix);
255     std::string keys = "test_";
256     std::shared_ptr<KvStoreResultSet> resultSet;
257     size_t sum = 10;
258     for (size_t i = 0; i < sum; i++) {
259         singleKvStore_->Put(prefix + keys + std::to_string(i), keys + std::to_string(i));
260     }
261     singleKvStore_->GetResultSet(dataQuery, resultSet);
262     auto status = singleKvStore_->GetResultSet(prefix, resultSet);
263     if (status != Status::SUCCESS || resultSet == nullptr) {
264         return;
265     }
266     int cnt = resultSet->GetCount();
267     if (static_cast<int>(size) != cnt) {
268         return;
269     }
270     resultSet->GetPosition();
271     resultSet->IsBeforeFirst();
272     resultSet->IsFirst();
273     resultSet->MoveToPrevious();
274     resultSet->IsBeforeFirst();
275     resultSet->IsFirst();
276     while (resultSet->MoveToNext()) {
277         Entry entry;
278         resultSet->GetEntry(entry);
279     }
280     Entry entry;
281     resultSet->GetEntry(entry);
282     resultSet->IsLast();
283     resultSet->IsAfterLast();
284     resultSet->MoveToNext();
285     resultSet->IsLast();
286     resultSet->IsAfterLast();
287     resultSet->Move(1);
288     resultSet->IsLast();
289     resultSet->IsAfterLast();
290     resultSet->MoveToFirst();
291     resultSet->GetEntry(entry);
292     resultSet->MoveToLast();
293     resultSet->GetEntry(entry);
294     for (size_t i = 0; i < sum; i++) {
295         singleKvStore_->Delete(prefix + keys + std::to_string(i));
296     }
297 }
298 
GetCountFuzz1(const uint8_t * data,size_t size)299 void GetCountFuzz1(const uint8_t *data, size_t size)
300 {
301     int count;
302     std::string prefix(data, data + size);
303     DataQuery query;
304     query.KeyPrefix(prefix);
305     std::string keys = "test_";
306     size_t sum = 10;
307     for (size_t i = 0; i < sum; i++) {
308         singleKvStore_->Put(prefix + keys + std::to_string(i), keys + std::to_string(i));
309     }
310     singleKvStore_->GetCount(query, count);
311     for (size_t i = 0; i < sum; i++) {
312         singleKvStore_->Delete(prefix + keys + std::to_string(i));
313     }
314 }
315 
GetCountFuzz2(const uint8_t * data,size_t size)316 void GetCountFuzz2(const uint8_t *data, size_t size)
317 {
318     int count;
319     size_t sum = 10;
320     std::vector<std::string> keys;
321     std::string prefix(data, data + size);
322     for (size_t i = 0; i < sum; i++) {
323         keys.push_back(prefix);
324     }
325     DataQuery query;
326     query.InKeys(keys);
327     std::string skey = "test_";
328     for (size_t i = 0; i < sum; i++) {
329         singleKvStore_->Put(prefix + skey + std::to_string(i), skey + std::to_string(i));
330     }
331     singleKvStore_->GetCount(query, count);
332     for (size_t i = 0; i < sum; i++) {
333         singleKvStore_->Delete(prefix + skey + std::to_string(i));
334     }
335 }
336 
RemoveDeviceDataFuzz(const uint8_t * data,size_t size)337 void RemoveDeviceDataFuzz(const uint8_t *data, size_t size)
338 {
339     size_t sum = 10;
340     std::string deviceId(data, data + size);
341     std::vector<Entry> input;
342     auto cmp = [](const Key &entry, const Key &sentry) { return entry.Data() < sentry.Data(); };
343     std::map<Key, Value, decltype(cmp)> dictionary(cmp);
344     for (size_t i = 0; i < sum; ++i) {
345         Entry entry;
346         entry.key = std::to_string(i).append("_k");
347         entry.value = std::to_string(i).append("_v");
348         dictionary[entry.key] = entry.value;
349         input.push_back(entry);
350     }
351     singleKvStore_->PutBatch(input);
352     singleKvStore_->RemoveDeviceData(deviceId);
353     singleKvStore_->RemoveDeviceData("");
354 
355     for (size_t i = 0; i < sum; i++) {
356         singleKvStore_->Delete(std::to_string(i).append("_k"));
357     }
358 }
359 
GetSecurityLevelFuzz(const uint8_t * data,size_t size)360 void GetSecurityLevelFuzz(const uint8_t *data, size_t size)
361 {
362     size_t sum = 10;
363     std::vector<std::string> keys;
364     std::string prefix(data, data + size);
365     for (size_t i = 0; i < sum; i++) {
366         keys.push_back(prefix);
367     }
368     std::string skey = "test_";
369     for (size_t i = 0; i < sum; i++) {
370         singleKvStore_->Put(prefix + skey + std::to_string(i), skey + std::to_string(i));
371     }
372     SecurityLevel securityLevel;
373     singleKvStore_->GetSecurityLevel(securityLevel);
374     for (size_t i = 0; i < sum; i++) {
375         singleKvStore_->Delete(prefix + skey + std::to_string(i));
376     }
377 }
378 
SyncFuzz1(const uint8_t * data,size_t size)379 void SyncFuzz1(const uint8_t *data, size_t size)
380 {
381     size_t sum = 10;
382     std::string skey = "test_";
383     for (size_t i = 0; i < sum; i++) {
384         singleKvStore_->Put(skey + std::to_string(i), skey + std::to_string(i));
385     }
386     std::string deviceId(data, data + size);
387     std::vector<std::string> deviceIds = { deviceId };
388     uint32_t allowedDelayMs = 200;
389     singleKvStore_->Sync(deviceIds, SyncMode::PUSH, allowedDelayMs);
390     for (size_t i = 0; i < sum; i++) {
391         singleKvStore_->Delete(skey + std::to_string(i));
392     }
393 }
394 
SyncFuzz2(const uint8_t * data,size_t size)395 void SyncFuzz2(const uint8_t *data, size_t size)
396 {
397     size_t sum = 10;
398     std::string skey = "test_";
399     for (size_t i = 0; i < sum; i++) {
400         singleKvStore_->Put(skey + std::to_string(i), skey + std::to_string(i));
401     }
402     std::string deviceId(data, data + size);
403     std::vector<std::string> deviceIds = { deviceId };
404     DataQuery dataQuery;
405     dataQuery.KeyPrefix("name");
406     singleKvStore_->Sync(deviceIds, SyncMode::PULL, dataQuery, nullptr);
407     for (size_t i = 0; i < sum; i++) {
408         singleKvStore_->Delete(skey + std::to_string(i));
409     }
410 }
411 
SyncParamFuzz(const uint8_t * data,size_t size)412 void SyncParamFuzz(const uint8_t *data, size_t size)
413 {
414     size_t sum = 10;
415     std::vector<std::string> keys;
416     std::string prefix(data, data + size);
417     for (size_t i = 0; i < sum; i++) {
418         keys.push_back(prefix);
419     }
420     std::string skey = "test_";
421     for (size_t i = 0; i < sum; i++) {
422         singleKvStore_->Put(prefix + skey + std::to_string(i), skey + std::to_string(i));
423     }
424 
425     KvSyncParam syncParam { 500 };
426     singleKvStore_->SetSyncParam(syncParam);
427 
428     KvSyncParam syncParamRet;
429     singleKvStore_->GetSyncParam(syncParamRet);
430 
431     for (size_t i = 0; i < sum; i++) {
432         singleKvStore_->Delete(prefix + skey + std::to_string(i));
433     }
434 }
435 
SetCapabilityEnabledFuzz(const uint8_t * data,size_t size)436 void SetCapabilityEnabledFuzz(const uint8_t *data, size_t size)
437 {
438     size_t sum = 10;
439     std::vector<std::string> keys;
440     std::string prefix(data, data + size);
441     for (size_t i = 0; i < sum; i++) {
442         keys.push_back(prefix);
443     }
444     std::string skey = "test_";
445     for (size_t i = 0; i < sum; i++) {
446         singleKvStore_->Put(prefix + skey + std::to_string(i), skey + std::to_string(i));
447     }
448 
449     singleKvStore_->SetCapabilityEnabled(true);
450     singleKvStore_->SetCapabilityEnabled(false);
451 
452     for (size_t i = 0; i < sum; i++) {
453         singleKvStore_->Delete(prefix + skey + std::to_string(i));
454     }
455 }
456 
SetCapabilityRangeFuzz(const uint8_t * data,size_t size)457 void SetCapabilityRangeFuzz(const uint8_t *data, size_t size)
458 {
459     std::string label(data, data + size);
460     std::vector<std::string> local = { label + "_local1", label + "_local2" };
461     std::vector<std::string> remote = { label + "_remote1", label + "_remote2" };
462     singleKvStore_->SetCapabilityRange(local, remote);
463 }
464 
SubscribeWithQueryFuzz(const uint8_t * data,size_t size)465 void SubscribeWithQueryFuzz(const uint8_t *data, size_t size)
466 {
467     std::string deviceId(data, data + size);
468     std::vector<std::string> deviceIds = { deviceId + "_1", deviceId + "_2" };
469     DataQuery dataQuery;
470     dataQuery.KeyPrefix("name");
471     singleKvStore_->SubscribeWithQuery(deviceIds, dataQuery);
472     singleKvStore_->UnsubscribeWithQuery(deviceIds, dataQuery);
473 }
474 
UnSubscribeWithQueryFuzz(const uint8_t * data,size_t size)475 void UnSubscribeWithQueryFuzz(const uint8_t *data, size_t size)
476 {
477     std::string deviceId(data, data + size);
478     std::vector<std::string> deviceIds = { deviceId + "_1", deviceId + "_2" };
479     DataQuery dataQuery;
480     dataQuery.KeyPrefix("name");
481     singleKvStore_->UnsubscribeWithQuery(deviceIds, dataQuery);
482 }
483 
AsyncGetFuzz(const uint8_t * data,size_t size)484 void AsyncGetFuzz(const uint8_t *data, size_t size)
485 {
486     std::string strKey(data, data + size);
487     std::string strValue(data, data + size);
488     Key key = { strKey };
489     Value val = { strValue };
490     singleKvStore_->Put(key, val);
491     Value out;
492     std::function<void(Status, Value &&)> call = [](Status status, Value &&value) {};
493     std::string networkId(data, data + size);
494     singleKvStore_->Get(key, networkId, call);
495     singleKvStore_->Delete(key);
496 }
497 
AsyncGetEntriesFuzz(const uint8_t * data,size_t size)498 void AsyncGetEntriesFuzz(const uint8_t *data, size_t size)
499 {
500     std::string prefix(data, data + size);
501     std::string keys = "test_";
502     size_t sum = 10;
503     std::vector<Entry> results;
504     for (size_t i = 0; i < sum; i++) {
505         singleKvStore_->Put(prefix + keys + std::to_string(i), { keys + std::to_string(i) });
506     }
507     std::function<void(Status, std::vector<Entry> &&)> call = [](Status status, std::vector<Entry> &&entry) {};
508     std::string networkId(data, data + size);
509     singleKvStore_->GetEntries(prefix, networkId, call);
510     for (size_t i = 0; i < sum; i++) {
511         singleKvStore_->Delete(prefix + keys + std::to_string(i));
512     }
513 }
514 } // namespace OHOS
515 
516 /* Fuzzer entry point */
LLVMFuzzerTestOneInput(const uint8_t * data,size_t size)517 extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
518 {
519     /* Run your code on data */
520     OHOS::SetUpTestCase();
521     OHOS::PutFuzz(data, size);
522     OHOS::PutBatchFuzz(data, size);
523     OHOS::GetFuzz(data, size);
524     OHOS::GetEntriesFuzz1(data, size);
525     OHOS::GetEntriesFuzz2(data, size);
526     OHOS::GetResultSetFuzz1(data, size);
527     OHOS::GetResultSetFuzz2(data, size);
528     OHOS::GetResultSetFuzz3(data, size);
529     OHOS::GetCountFuzz1(data, size);
530     OHOS::GetCountFuzz2(data, size);
531     OHOS::SyncFuzz1(data, size);
532     OHOS::SyncFuzz2(data, size);
533     OHOS::SubscribeKvStoreFuzz(data, size);
534     OHOS::RemoveDeviceDataFuzz(data, size);
535     OHOS::GetSecurityLevelFuzz(data, size);
536     OHOS::SyncCallbackFuzz(data, size);
537     OHOS::SyncParamFuzz(data, size);
538     OHOS::SetCapabilityEnabledFuzz(data, size);
539     OHOS::SetCapabilityRangeFuzz(data, size);
540     OHOS::SubscribeWithQueryFuzz(data, size);
541     OHOS::UnSubscribeWithQueryFuzz(data, size);
542     OHOS::AsyncGetFuzz(data, size);
543     OHOS::AsyncGetEntriesFuzz(data, size);
544     OHOS::TearDown();
545     return 0;
546 }