blob: 0e44612f8e0a37bee97e0f16e6e3e8c1f7af56b1 [file] [log] [blame]
// Copyright 2020 The Fuchsia 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 <lib/async-testing/test_loop.h>
#include <fuzzer/FuzzedDataProvider.h>
#include "src/connectivity/bluetooth/core/bt-host/common/byte_buffer.h"
#include "src/connectivity/bluetooth/core/bt-host/hci-spec/protocol.h"
#include "src/connectivity/bluetooth/core/bt-host/l2cap/bredr_dynamic_channel.h"
#include "src/connectivity/bluetooth/core/bt-host/l2cap/bredr_signaling_channel.h"
#include "src/connectivity/bluetooth/core/bt-host/l2cap/fake_channel.h"
constexpr static bt::hci::ConnectionHandle kTestHandle = 0x0001;
bt::l2cap::ChannelParameters ConsumeChannelParameters(FuzzedDataProvider& provider) {
bt::l2cap::ChannelParameters params;
bool use_defaults = provider.ConsumeBool();
if (use_defaults) {
return params;
}
params.mode = provider.ConsumeBool() ? bt::l2cap::ChannelMode::kBasic
: bt::l2cap::ChannelMode::kEnhancedRetransmission;
params.max_rx_sdu_size = provider.ConsumeIntegral<uint16_t>();
return params;
}
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
FuzzedDataProvider provider(data, size);
// Sets dispatcher needed for signaling channel reponse timeout.
async::TestLoop loop;
auto fake_chan = fbl::AdoptRef(new bt::l2cap::testing::FakeChannel(
bt::l2cap::kSignalingChannelId, bt::l2cap::kSignalingChannelId, kTestHandle,
bt::hci::Connection::LinkType::kACL));
bt::l2cap::internal::BrEdrSignalingChannel sig_chan(fake_chan,
bt::hci::Connection::Role::kMaster);
auto open_cb = [](auto chan) {};
auto close_cb = [](auto chan) {};
auto service_chan_cb = [](auto chan) {};
auto service_cb = [&](auto psm) {
// Reject some PSMs.
if (provider.ConsumeBool()) {
return std::optional<bt::l2cap::internal::DynamicChannelRegistry::ServiceInfo>();
}
auto params = ConsumeChannelParameters(provider);
return std::optional(
bt::l2cap::internal::DynamicChannelRegistry::ServiceInfo(params, service_chan_cb));
};
bt::l2cap::internal::BrEdrDynamicChannelRegistry registry(&sig_chan, close_cb, service_cb,
/*random_channel_ids=*/true);
while (provider.remaining_bytes() > 0) {
// Receive an l2cap packet.
uint16_t data_size = provider.ConsumeIntegral<uint16_t>();
auto data = provider.ConsumeBytes<uint8_t>(data_size);
fake_chan->Receive(bt::BufferView(data.data(), data.size()));
if (provider.ConsumeBool()) {
registry.OpenOutbound(bt::l2cap::kAVDTP, ConsumeChannelParameters(provider), open_cb);
}
if (provider.ConsumeBool()) {
loop.RunFor(bt::l2cap::kSignalingChannelResponseTimeout);
}
}
return 0;
}