blob: ac6e13b2238dddace0271815edb46e1941489c69 [file] [log] [blame]
Prashant Malani519dd742018-03-15 22:01:50 -07001// Copyright 2018 The Chromium OS Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4//
5#include "midis/seq_handler.h"
6
7#include <string>
8
9#include <base/bind.h>
Prashant Malanie6e6b272018-05-02 10:16:30 -070010#include <base/logging.h>
Prashant Malani519dd742018-03-15 22:01:50 -070011
12#include "midis/device.h"
13
Prashant Malanie6e6b272018-05-02 10:16:30 -070014namespace {
15
16const int kFakeOutputPort = 0;
17}
18
Prashant Malani519dd742018-03-15 22:01:50 -070019namespace midis {
20
21// We don't have a real device whose callbacks we can run, so instead,
22// we just create FakeCallbacks which contains stubs.
23class FakeCallbacks {
24 public:
25 void AddDevice(std::unique_ptr<Device> device) {}
26 void RemoveDevice(uint32_t card_num, uint32_t device_num) {}
27 void HandleReceiveData(uint32_t card_id,
28 uint32_t device_id,
29 uint32_t port_id,
30 const char* buffer,
31 size_t buf_len) {}
32 bool IsDevicePresent(uint32_t card_num, uint32_t device_num) {
33 // Unused in the fuzzer, so doesn't matter.
34 return true;
35 }
36 bool IsPortPresent(uint32_t card_num, uint32_t device_num, uint32_t port_id) {
37 // Unused in the fuzzer, so doesn't matter.
38 return true;
39 }
40};
41
42// Running a fuzz test on the SeqHandler requires us to set certain
43// private variables inside SeqHandler. To allow this to happen,
44// we encapsulate the SeqHandler inside a FuzzerRunner class,
45// and make FuzzerRunner a friend of SeqHandler.
46class SeqHandlerFuzzer {
47 public:
48 void SetUpSeqHandler() {
49 seq_handler_ = std::make_unique<SeqHandler>(
50 base::Bind(&FakeCallbacks::AddDevice, base::Unretained(&callbacks_)),
51 base::Bind(&FakeCallbacks::RemoveDevice, base::Unretained(&callbacks_)),
52 base::Bind(&FakeCallbacks::HandleReceiveData,
53 base::Unretained(&callbacks_)),
54 base::Bind(&FakeCallbacks::IsDevicePresent,
55 base::Unretained(&callbacks_)),
56 base::Bind(&FakeCallbacks::IsPortPresent,
57 base::Unretained(&callbacks_)));
58
59 seq_handler_->decoder_ = midis::SeqHandler::CreateMidiEvent(0);
60 }
61
Prashant Malanie6e6b272018-05-02 10:16:30 -070062 bool SetUpOutputPort() {
63 snd_seq_t* tmp_seq = nullptr;
64
65 int err = snd_seq_open(&tmp_seq, "hw", SND_SEQ_OPEN_OUTPUT, 0);
66 if (err != 0) {
67 LOG(ERROR) << "snd_seq_open fails: " << snd_strerror(err);
68 return false;
69 }
70
71 SeqHandler::ScopedSeqPtr out_client(tmp_seq);
72 tmp_seq = nullptr;
73 seq_handler_->out_client_ = std::move(out_client);
74 seq_handler_->out_client_id_ =
75 snd_seq_client_id(seq_handler_->out_client_.get());
76 return true;
77 }
78
Prashant Malani519dd742018-03-15 22:01:50 -070079 // Send arbitrary data to ProcessMidiEvent() and see what happens.
80 void ProcessMidiEvent(const uint8_t* data, size_t size) {
81 snd_seq_event_t event;
82 size_t bytes_to_copy = sizeof(snd_seq_event_t);
83 if (size < bytes_to_copy) {
84 bytes_to_copy = size;
85 }
86 memcpy(&event, data, bytes_to_copy);
87 seq_handler_->ProcessMidiEvent(&event);
88 }
89
Prashant Malanie6e6b272018-05-02 10:16:30 -070090 void SendMidiData(const uint8_t* data, size_t size) {
91 // We don't have a real output port, so we just supply a value.
92 // This ALSA seq interface should fail gracefully.
93 seq_handler_->SendMidiData(kFakeOutputPort, data, size);
94 }
95
Prashant Malani519dd742018-03-15 22:01:50 -070096 private:
97 std::unique_ptr<SeqHandler> seq_handler_;
98 FakeCallbacks callbacks_;
99};
100
Prashant Malanie6e6b272018-05-02 10:16:30 -0700101struct Environment {
Tom Hughesaebcdce2020-08-27 15:18:39 -0700102 Environment() { logging::SetMinLogLevel(logging::LOG_ERROR); }
Prashant Malanie6e6b272018-05-02 10:16:30 -0700103};
104
105Environment* env = new Environment();
106
Prashant Malani519dd742018-03-15 22:01:50 -0700107} // namespace midis
108
109extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
110 midis::SeqHandlerFuzzer fuzzer;
111 fuzzer.SetUpSeqHandler();
Prashant Malanie6e6b272018-05-02 10:16:30 -0700112 if (!fuzzer.SetUpOutputPort()) {
113 abort();
114 }
Prashant Malani519dd742018-03-15 22:01:50 -0700115 fuzzer.ProcessMidiEvent(data, size);
Prashant Malanie6e6b272018-05-02 10:16:30 -0700116 fuzzer.SendMidiData(data, size);
Prashant Malani519dd742018-03-15 22:01:50 -0700117 return 0;
118}