blob: 2ed680d31a4933c6451ac410fa72f2e2e406cb8a [file] [log] [blame]
// Copyright 2022 The ChromiumOS Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <cstddef>
#include <cstdint>
#include <memory>
#include <base/logging.h>
#include <base/notreached.h>
#include <dbus/message.h>
#include <dbus/rgbkbd/dbus-constants.h>
#include <fuzzer/FuzzedDataProvider.h>
#include <rgbkbd/rgbkbd_daemon.h>
namespace rgbkbd {
namespace {
const int kEnumSizeInBytes = 1;
// Check that capability enum size < 255.
static_assert(static_cast<uint8_t>(RgbKeyboardCapabilities::kMaxValue) <=
std::numeric_limits<uint8_t>::max());
// 1 byte for random (0-4) range for branch switch, 1 byte for random uint8_t
// enum for capabilities, 3 bytes min for {r,g,b} (uint8_t), 4 bytes for branch
// value (int).
const int kMinBytes = 8 + kEnumSizeInBytes;
} // namespace
class Environment {
public:
Environment() {
logging::SetMinLogLevel(logging::LOGGING_FATAL); // <- DISABLE LOGGING.
}
};
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
static Environment env;
dbus::Bus::Options options;
scoped_refptr<dbus::Bus> bus = new dbus::Bus(options);
auto adaptor_ = std::make_unique<DBusAdaptor>(bus, /*cros_config=*/nullptr,
/*crossystem=*/nullptr,
/*daemon=*/nullptr);
FuzzedDataProvider provider(data, size);
// Must have at least kEnumSizeInBytes available to set initial testing
// capability.
if (size < kEnumSizeInBytes) {
return 0;
}
// Start with testing mode enabled.
const uint8_t initial_capability = provider.ConsumeIntegralInRange<uint8_t>(
0, static_cast<uint8_t>(RgbKeyboardCapabilities::kMaxValue));
adaptor_->SetTestingMode(/*enable_testing=*/true,
static_cast<uint32_t>(initial_capability));
while (provider.remaining_bytes() >= kMinBytes) {
const int branch = provider.ConsumeIntegralInRange<int8_t>(0, 4);
switch (branch) {
case 0: {
adaptor_->SetCapsLockState(provider.ConsumeBool());
break;
}
case 1: {
const uint8_t r = provider.ConsumeIntegral<uint8_t>();
const uint8_t g = provider.ConsumeIntegral<uint8_t>();
const uint8_t b = provider.ConsumeIntegral<uint8_t>();
adaptor_->SetStaticBackgroundColor(r, g, b);
break;
}
case 2: {
adaptor_->SetRainbowMode();
break;
}
case 3: {
const uint32_t capability = provider.ConsumeIntegralInRange<uint8_t>(
0, static_cast<uint8_t>(RgbKeyboardCapabilities::kMaxValue));
adaptor_->SetTestingMode(/*enable_testing=*/true,
static_cast<uint32_t>(capability));
break;
}
case 4: {
const int zone = provider.ConsumeIntegral<int>();
const uint8_t r = provider.ConsumeIntegral<uint8_t>();
const uint8_t g = provider.ConsumeIntegral<uint8_t>();
const uint8_t b = provider.ConsumeIntegral<uint8_t>();
adaptor_->SetZoneColor(zone, r, g, b);
break;
}
default: {
NOTREACHED();
break;
}
}
}
return 0;
}
} // namespace rgbkbd