Skip to content

Commit aedae62

Browse files
nathaniel-broughhathach
authored andcommitted
fuzz: Add support for fuzzing
Adds support for fuzzing with basic cdc fuzzer.
1 parent ab8cfb3 commit aedae62

File tree

14 files changed

+1269
-0
lines changed

14 files changed

+1269
-0
lines changed

fuzz/dcd_fuzz.cc

Lines changed: 202 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,202 @@
1+
/*
2+
* The MIT License (MIT)
3+
*
4+
* Copyright (c) 2022 Nathaniel Brough
5+
*
6+
* Permission is hereby granted, free of charge, to any person obtaining a copy
7+
* of this software and associated documentation files (the "Software"), to deal
8+
* in the Software without restriction, including without limitation the rights
9+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10+
* copies of the Software, and to permit persons to whom the Software is
11+
* furnished to do so, subject to the following conditions:
12+
*
13+
* The above copyright notice and this permission notice shall be included in
14+
* all copies or substantial portions of the Software.
15+
*
16+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22+
* THE SOFTWARE.
23+
*
24+
*/
25+
#include "device/dcd.h"
26+
#include "fuzz/fuzz_private.h"
27+
#include <assert.h>
28+
#include <cstdint>
29+
#include <limits>
30+
31+
#define UNUSED(x) (void)(x)
32+
33+
//--------------------------------------------------------------------+
34+
// State tracker
35+
//--------------------------------------------------------------------+
36+
struct State {
37+
bool interrupts_enabled;
38+
bool sof_enabled;
39+
uint8_t address;
40+
};
41+
42+
static State state = {false, 0, 0};
43+
44+
//--------------------------------------------------------------------+
45+
// Controller API
46+
// All no-ops as we are fuzzing.
47+
//--------------------------------------------------------------------+
48+
extern "C" {
49+
void dcd_init(uint8_t rhport) {
50+
UNUSED(rhport);
51+
return;
52+
}
53+
54+
void dcd_int_handler(uint8_t rhport) {
55+
assert(_fuzz_data_provider.has_value());
56+
57+
if (!state.interrupts_enabled) {
58+
return;
59+
}
60+
61+
// Choose if we want to generate a signal based on the fuzzed data.
62+
if (_fuzz_data_provider->ConsumeBool()) {
63+
dcd_event_bus_signal(
64+
rhport,
65+
// Choose a random event based on the fuzz data.
66+
(dcd_eventid_t)_fuzz_data_provider->ConsumeIntegralInRange<uint8_t>(
67+
DCD_EVENT_INVALID + 1, DCD_EVENT_COUNT - 1),
68+
// Identify trigger as either an interrupt or a syncrhonous call
69+
// depending on fuzz data.
70+
_fuzz_data_provider->ConsumeBool());
71+
}
72+
73+
if (_fuzz_data_provider->ConsumeBool()) {
74+
constexpr size_t kSetupFrameLength = 8;
75+
std::vector<uint8_t> setup =
76+
_fuzz_data_provider->ConsumeBytes<uint8_t>(kSetupFrameLength);
77+
// Fuzz consumer may return less than requested. If this is the case
78+
// we want to make sure that at least that length is allocated and available
79+
// to the signal handler.
80+
if (setup.size() != kSetupFrameLength) {
81+
setup.resize(kSetupFrameLength);
82+
}
83+
dcd_event_setup_received(rhport, setup.data(),
84+
// Identify trigger as either an interrupt or a
85+
// syncrhonous call depending on fuzz data.
86+
_fuzz_data_provider->ConsumeBool());
87+
}
88+
}
89+
90+
void dcd_int_enable(uint8_t rhport) {
91+
state.interrupts_enabled = true;
92+
UNUSED(rhport);
93+
return;
94+
}
95+
96+
void dcd_int_disable(uint8_t rhport) {
97+
state.interrupts_enabled = false;
98+
UNUSED(rhport);
99+
return;
100+
}
101+
102+
void dcd_set_address(uint8_t rhport, uint8_t dev_addr) {
103+
UNUSED(rhport);
104+
state.address = dev_addr;
105+
// Respond with status.
106+
dcd_edpt_xfer(rhport, tu_edpt_addr(0, TUSB_DIR_IN), NULL, 0);
107+
return;
108+
}
109+
110+
void dcd_remote_wakeup(uint8_t rhport) {
111+
UNUSED(rhport);
112+
return;
113+
}
114+
115+
void dcd_connect(uint8_t rhport) {
116+
UNUSED(rhport);
117+
return;
118+
}
119+
120+
void dcd_disconnect(uint8_t rhport) {
121+
UNUSED(rhport);
122+
return;
123+
}
124+
125+
void dcd_sof_enable(uint8_t rhport, bool en) {
126+
state.sof_enabled = en;
127+
UNUSED(rhport);
128+
return;
129+
}
130+
131+
//--------------------------------------------------------------------+
132+
// Endpoint API
133+
//--------------------------------------------------------------------+
134+
135+
// Configure endpoint's registers according to descriptor
136+
bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const *desc_ep) {
137+
UNUSED(rhport);
138+
UNUSED(desc_ep);
139+
return _fuzz_data_provider->ConsumeBool();
140+
}
141+
142+
// Close all non-control endpoints, cancel all pending transfers if any.
143+
// Invoked when switching from a non-zero Configuration by SET_CONFIGURE
144+
// therefore required for multiple configuration support.
145+
void dcd_edpt_close_all(uint8_t rhport) {
146+
UNUSED(rhport);
147+
return;
148+
}
149+
150+
// Close an endpoint.
151+
// Since it is weak, caller must TU_ASSERT this function's existence before
152+
// calling it.
153+
void dcd_edpt_close(uint8_t rhport, uint8_t ep_addr) {
154+
UNUSED(rhport);
155+
UNUSED(ep_addr);
156+
return;
157+
}
158+
159+
// Submit a transfer, When complete dcd_event_xfer_complete() is invoked to
160+
// notify the stack
161+
bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer,
162+
uint16_t total_bytes) {
163+
UNUSED(rhport);
164+
UNUSED(buffer);
165+
UNUSED(total_bytes);
166+
167+
uint8_t const dir = tu_edpt_dir(ep_addr);
168+
169+
if (dir == TUSB_DIR_IN) {
170+
std::vector<uint8_t> temp =
171+
_fuzz_data_provider->ConsumeBytes<uint8_t>(total_bytes);
172+
std::copy(temp.begin(), temp.end(), buffer);
173+
}
174+
// Ignore output data as it's not useful for fuzzing without a more
175+
// complex fuzzed backend.
176+
177+
return _fuzz_data_provider->ConsumeBool();
178+
}
179+
180+
/* TODO: implement a fuzzed version of this.
181+
bool dcd_edpt_xfer_fifo(uint8_t rhport, uint8_t ep_addr, tu_fifo_t *ff,
182+
uint16_t total_bytes) {}
183+
*/
184+
185+
// Stall endpoint, any queuing transfer should be removed from endpoint
186+
void dcd_edpt_stall(uint8_t rhport, uint8_t ep_addr) {
187+
188+
UNUSED(rhport);
189+
UNUSED(ep_addr);
190+
return;
191+
}
192+
193+
// clear stall, data toggle is also reset to DATA0
194+
// This API never calls with control endpoints, since it is auto cleared when
195+
// receiving setup packet
196+
void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr) {
197+
198+
UNUSED(rhport);
199+
UNUSED(ep_addr);
200+
return;
201+
}
202+
}

fuzz/device/cdc/CMakeLists.txt

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
cmake_minimum_required(VERSION 3.5)
2+
3+
include(${CMAKE_CURRENT_SOURCE_DIR}/../../../hw/bsp/family_support.cmake)
4+
5+
# gets PROJECT name for the example (e.g. <BOARD>-<DIR_NAME>)
6+
family_get_project_name(PROJECT ${CMAKE_CURRENT_LIST_DIR})
7+
8+
project(${PROJECT})
9+
10+
# Checks this example is valid for the family and initializes the project
11+
family_initialize_project(${PROJECT} ${CMAKE_CURRENT_LIST_DIR})
12+
13+
add_executable(${PROJECT})
14+
15+
# Example source
16+
target_sources(${PROJECT} PUBLIC
17+
${CMAKE_CURRENT_SOURCE_DIR}/src/main.c
18+
${CMAKE_CURRENT_SOURCE_DIR}/src/msc_disk.c
19+
${CMAKE_CURRENT_SOURCE_DIR}/src/usb_descriptors.c
20+
)
21+
22+
# Example include
23+
target_include_directories(${PROJECT} PUBLIC
24+
${CMAKE_CURRENT_SOURCE_DIR}/src
25+
)
26+
27+
# Configure compilation flags and libraries for the example... see the corresponding function
28+
# in hw/bsp/FAMILY/family.cmake for details.
29+
family_configure_device_example(${PROJECT})

fuzz/device/cdc/Makefile

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
include ../../../tools/top.mk
2+
include ../../make.mk
3+
4+
INC += \
5+
src \
6+
$(TOP)/hw \
7+
8+
# Example source
9+
SRC_C += $(addprefix $(CURRENT_PATH)/, $(wildcard src/*.c))
10+
SRC_CXX += $(addprefix $(CURRENT_PATH)/, $(wildcard src/*.cc))
11+
12+
include ../../rules.mk

fuzz/device/cdc/skip.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
mcu:SAMD11

0 commit comments

Comments
 (0)