/src/tinyusb/test/fuzz/msc_fuzz.cc
Line | Count | Source |
1 | | #include "fuzz/fuzz_private.h" |
2 | | #include "tusb.h" |
3 | | #include <cassert> |
4 | | #include <array> |
5 | | #include <limits> |
6 | | |
7 | | #if CFG_TUD_MSC==1 |
8 | | |
9 | | // Whether host does safe eject. |
10 | | // tud_msc_get_maxlun_cb returns a uint8_t so the max logical units that are |
11 | | // allowed is 255, so we need to keep track of 255 fuzzed logical units. |
12 | | static std::array<bool, std::numeric_limits<uint8_t>::max()> ejected = {false}; |
13 | | |
14 | | extern "C" { |
15 | | // Invoked when received SCSI_CMD_INQUIRY |
16 | | // Application fill vendor id, product id and revision with string up to 8, 16, |
17 | | // 4 characters respectively |
18 | | void tud_msc_inquiry_cb(uint8_t lun, uint8_t vendor_id[8], |
19 | | uint8_t product_id[16], uint8_t product_rev[4]) { |
20 | | (void)lun; |
21 | | assert(_fuzz_data_provider.has_value()); |
22 | | |
23 | | std::string vid = _fuzz_data_provider->ConsumeBytesAsString(8); |
24 | | std::string pid = _fuzz_data_provider->ConsumeBytesAsString(16); |
25 | | std::string rev = _fuzz_data_provider->ConsumeBytesAsString(4); |
26 | | |
27 | | memcpy(vendor_id, vid.c_str(), strlen(vid.c_str())); |
28 | | memcpy(product_id, pid.c_str(), strlen(pid.c_str())); |
29 | | memcpy(product_rev, rev.c_str(), strlen(rev.c_str())); |
30 | | } |
31 | | |
32 | | // Invoked when received Test Unit Ready command. |
33 | | // return true allowing host to read/write this LUN e.g SD card inserted |
34 | 0 | bool tud_msc_test_unit_ready_cb(uint8_t lun) { |
35 | | // RAM disk is ready until ejected |
36 | 0 | if (ejected[lun]) { |
37 | | // Additional Sense 3A-00 is NOT_FOUND |
38 | 0 | tud_msc_set_sense(lun, SCSI_SENSE_NOT_READY, 0x3a, 0x00); |
39 | 0 | return false; |
40 | 0 | } |
41 | | |
42 | 0 | return _fuzz_data_provider->ConsumeBool(); |
43 | 0 | } |
44 | | |
45 | | // Invoked when received SCSI_CMD_READ_CAPACITY_10 and |
46 | | // SCSI_CMD_READ_FORMAT_CAPACITY to determine the disk size Application update |
47 | | // block count and block size |
48 | | void tud_msc_capacity_cb(uint8_t lun, uint32_t *block_count, |
49 | 0 | uint16_t *block_size) { |
50 | 0 | (void)lun; |
51 | 0 | *block_count = _fuzz_data_provider->ConsumeIntegral<uint32_t>(); |
52 | 0 | *block_size = _fuzz_data_provider->ConsumeIntegral<uint16_t>(); |
53 | 0 | } |
54 | | |
55 | | // Invoked when received Start Stop Unit command |
56 | | // - Start = 0 : stopped power mode, if load_eject = 1 : unload disk storage |
57 | | // - Start = 1 : active mode, if load_eject = 1 : load disk storage |
58 | | bool tud_msc_start_stop_cb(uint8_t lun, uint8_t power_condition, bool start, |
59 | | bool load_eject) { |
60 | | (void)power_condition; |
61 | | assert(_fuzz_data_provider.has_value()); |
62 | | |
63 | | if (load_eject) { |
64 | | if (start) { |
65 | | // load disk storage |
66 | | } else { |
67 | | // unload disk storage |
68 | | ejected[lun] = true; |
69 | | } |
70 | | } |
71 | | |
72 | | return _fuzz_data_provider->ConsumeBool(); |
73 | | } |
74 | | |
75 | | // Callback invoked when received READ10 command. |
76 | | // Copy disk's data to buffer (up to bufsize) and return number of copied bytes. |
77 | | int32_t tud_msc_read10_cb(uint8_t lun, uint32_t lba, uint32_t offset, |
78 | 0 | void *buffer, uint32_t bufsize) { |
79 | 0 | assert(_fuzz_data_provider.has_value()); |
80 | 0 | (void)lun; |
81 | 0 | (void)lba; |
82 | 0 | (void)offset; |
83 | |
|
84 | 0 | std::vector<uint8_t> consumed_buffer = _fuzz_data_provider->ConsumeBytes<uint8_t>( |
85 | 0 | _fuzz_data_provider->ConsumeIntegralInRange<uint32_t>(0, bufsize)); |
86 | 0 | memcpy(buffer, consumed_buffer.data(), consumed_buffer.size()); |
87 | | |
88 | | // Sometimes return an error code; |
89 | 0 | if (_fuzz_data_provider->ConsumeBool()) { |
90 | 0 | return _fuzz_data_provider->ConsumeIntegralInRange( |
91 | 0 | std::numeric_limits<int32_t>::min(), -1); |
92 | 0 | } |
93 | | |
94 | 0 | return consumed_buffer.size(); |
95 | 0 | } |
96 | | |
97 | | bool tud_msc_is_writable_cb(uint8_t lun) { |
98 | | assert(_fuzz_data_provider.has_value()); |
99 | | (void)lun; |
100 | | return _fuzz_data_provider->ConsumeBool(); |
101 | | } |
102 | | |
103 | | // Callback invoked when received WRITE10 command. |
104 | | // Process data in buffer to disk's storage and return number of written bytes |
105 | | int32_t tud_msc_write10_cb(uint8_t lun, uint32_t lba, uint32_t offset, |
106 | 0 | uint8_t *buffer, uint32_t bufsize) { |
107 | | // Ignore these as they are outputs and don't affect the return value. |
108 | 0 | (void)lun; |
109 | 0 | (void)lba; |
110 | 0 | (void)offset; |
111 | 0 | (void)buffer; |
112 | 0 | assert(_fuzz_data_provider.has_value()); |
113 | | |
114 | | // -ve error codes -> bufsize. |
115 | 0 | return _fuzz_data_provider->ConsumeIntegralInRange<int32_t>( |
116 | 0 | std::numeric_limits<int32_t>::min(), bufsize); |
117 | 0 | } |
118 | | |
119 | | // Callback invoked when received an SCSI command not in built-in list below |
120 | | // - READ_CAPACITY10, READ_FORMAT_CAPACITY, INQUIRY, MODE_SENSE6, REQUEST_SENSE |
121 | | // - READ10 and WRITE10 has their own callbacks |
122 | | int32_t tud_msc_scsi_cb(uint8_t lun, uint8_t const scsi_cmd[16], void *buffer, |
123 | 0 | uint16_t bufsize) { |
124 | 0 | (void)buffer; |
125 | 0 | (void)bufsize; |
126 | 0 | assert(_fuzz_data_provider.has_value()); |
127 | | |
128 | 0 | switch (scsi_cmd[0]) { |
129 | 0 | case SCSI_CMD_TEST_UNIT_READY: |
130 | 0 | break; |
131 | 0 | case SCSI_CMD_INQUIRY: |
132 | 0 | break; |
133 | 0 | case SCSI_CMD_MODE_SELECT_6: |
134 | 0 | break; |
135 | 0 | case SCSI_CMD_MODE_SENSE_6: |
136 | 0 | break; |
137 | 0 | case SCSI_CMD_START_STOP_UNIT: |
138 | 0 | break; |
139 | 0 | case SCSI_CMD_PREVENT_ALLOW_MEDIUM_REMOVAL: |
140 | 0 | break; |
141 | 0 | case SCSI_CMD_READ_CAPACITY_10: |
142 | 0 | break; |
143 | 0 | case SCSI_CMD_REQUEST_SENSE: |
144 | 0 | break; |
145 | 0 | case SCSI_CMD_READ_FORMAT_CAPACITY: |
146 | 0 | break; |
147 | 0 | case SCSI_CMD_READ_10: |
148 | 0 | break; |
149 | 0 | case SCSI_CMD_WRITE_10: |
150 | 0 | break; |
151 | 0 | default: |
152 | | // Set Sense = Invalid Command Operation |
153 | 0 | tud_msc_set_sense(lun, SCSI_SENSE_ILLEGAL_REQUEST, 0x20, 0x00); |
154 | 0 | return _fuzz_data_provider->ConsumeIntegralInRange<int32_t>( |
155 | 0 | std::numeric_limits<int32_t>::min(), -1); |
156 | 0 | } |
157 | | |
158 | 0 | return 0; |
159 | 0 | } |
160 | | } |
161 | | |
162 | | #endif |