blob: 0d7b0391769e346e6d65fabea38cd5ccd4e47832 [file] [log] [blame]
// Copyright 2019 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <stddef.h>
#include <stdint.h>
#include <base/logging.h>
#include <brillo/secure_blob.h>
#include <fuzzer/FuzzedDataProvider.h>
#include "chaps/object_store_impl.h"
class Environment {
public:
Environment() {
// Disable logging.
logging::SetMinLogLevel(logging::LOGGING_FATAL);
}
};
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
static Environment env;
FuzzedDataProvider data_provider(data, size);
chaps::ObjectStoreImpl store;
store.Init(base::FilePath(":memory:"));
std::string encryption_key = data_provider.ConsumeBytesAsString(32);
if (encryption_key.size() < 32) {
// We won't have any data to fuzz further, so no reason to even continue.
return 0;
}
store.SetEncryptionKey(brillo::SecureBlob(encryption_key));
// Randomly decide on operations to perform and save our last few blob_id's so
// that we can have valid ones to target better as well.
constexpr int kMaxBlobLength = 128;
std::vector<int> inserted_blob_ids;
// Grab the 3 bools for randomness on the final 3 operations now.
bool load_public_objects = data_provider.ConsumeBool();
bool load_private_objects = data_provider.ConsumeBool();
bool delete_all_objects = data_provider.ConsumeBool();
while (data_provider.remaining_bytes()) {
if (data_provider.ConsumeBool()) {
// Insert a new object.
int blob_id;
if (store.InsertObjectBlob(
{data_provider.ConsumeRandomLengthString(kMaxBlobLength),
data_provider.ConsumeBool()},
&blob_id)) {
inserted_blob_ids.push_back(blob_id);
}
}
if (data_provider.ConsumeBool()) {
// Update an object, randomly decide to update an existing one or use a
// random new ID.
if (!inserted_blob_ids.empty() && data_provider.ConsumeBool()) {
// Use an existing ID.
int blob_id =
inserted_blob_ids[data_provider.ConsumeIntegralInRange<int>(
0, inserted_blob_ids.size() - 1)];
store.UpdateObjectBlob(
blob_id, {data_provider.ConsumeRandomLengthString(kMaxBlobLength),
data_provider.ConsumeBool()});
} else {
// Generate a random blob ID for an update, if this succeeds add it to
// the list of inserted IDs.
int blob_id = data_provider.ConsumeIntegral<int>();
if (store.UpdateObjectBlob(
blob_id,
{data_provider.ConsumeRandomLengthString(kMaxBlobLength),
data_provider.ConsumeBool()})) {
inserted_blob_ids.push_back(blob_id);
}
}
}
if (data_provider.ConsumeBool()) {
// Delete an object.
if (!inserted_blob_ids.empty() && data_provider.ConsumeBool()) {
// Delete an existing object and remove it's ID from our list.
int random_index = data_provider.ConsumeIntegralInRange<int>(
0, inserted_blob_ids.size() - 1);
int blob_id = inserted_blob_ids[random_index];
inserted_blob_ids.erase(inserted_blob_ids.begin() + random_index);
store.DeleteObjectBlob(blob_id);
} else {
// Delete a random object ID.
store.DeleteObjectBlob(data_provider.ConsumeIntegral<int>());
}
}
}
// Randomly decide to load objects and delete them all.
std::map<int, chaps::ObjectBlob> blobs;
if (load_public_objects) {
store.LoadPublicObjectBlobs(&blobs);
}
if (load_private_objects) {
store.LoadPrivateObjectBlobs(&blobs);
}
if (delete_all_objects) {
store.DeleteAllObjectBlobs();
}
return 0;
}