/src/libcoap/tests/oss-fuzz/block_check_target.c
Line | Count | Source |
1 | | #include "coap3/coap_internal.h" |
2 | | #include <stdint.h> |
3 | | #include <string.h> |
4 | | |
5 | | static int |
6 | 18 | fuzz_event_handler(coap_session_t *session, const coap_event_t event) { |
7 | 18 | (void)session; |
8 | 18 | (void)event; |
9 | 18 | return 0; |
10 | 18 | } |
11 | | |
12 | | static uint8_t test_data[4096]; |
13 | | |
14 | | int |
15 | 36 | LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { |
16 | 36 | if (size < 20) { |
17 | 8 | return 0; |
18 | 8 | } |
19 | | |
20 | 114k | for (size_t i = 0; i < sizeof(test_data); i++) { |
21 | 114k | test_data[i] = (uint8_t)(i & 0xFF); |
22 | 114k | } |
23 | | |
24 | 28 | coap_startup(); |
25 | 28 | coap_set_log_level(COAP_LOG_EMERG); |
26 | 28 | coap_dtls_set_log_level(COAP_LOG_EMERG); |
27 | 28 | coap_debug_set_packet_loss("50%"); |
28 | 28 | coap_debug_set_packet_fail("100%"); |
29 | | |
30 | 28 | coap_context_t *ctx = coap_new_context(NULL); |
31 | 28 | if (!ctx) { |
32 | 0 | return 0; |
33 | 0 | } |
34 | 28 | coap_register_event_handler(ctx, fuzz_event_handler); |
35 | | |
36 | 28 | if (data[0] & 0x01) { |
37 | 13 | ctx->block_mode |= COAP_BLOCK_USE_LIBCOAP; |
38 | 13 | } |
39 | 28 | if (data[0] & 0x04) { |
40 | 11 | ctx->block_mode |= (COAP_BLOCK_USE_LIBCOAP | COAP_BLOCK_HAS_Q_BLOCK); |
41 | 11 | } |
42 | | |
43 | 28 | coap_address_t addr; |
44 | 28 | coap_address_init(&addr); |
45 | 28 | addr.addr.sa.sa_family = AF_INET; |
46 | | |
47 | 28 | coap_endpoint_t *ep = coap_new_endpoint(ctx, &addr, COAP_PROTO_UDP); |
48 | 28 | if (!ep) { |
49 | 0 | coap_free_context(ctx); |
50 | 0 | return 0; |
51 | 0 | } |
52 | | |
53 | 28 | coap_session_t *session = coap_new_client_session(ctx, NULL, &addr, |
54 | 28 | COAP_PROTO_UDP); |
55 | 28 | if (!session) { |
56 | 0 | coap_free_context(ctx); |
57 | 0 | return 0; |
58 | 0 | } |
59 | | |
60 | 28 | coap_str_const_t *uri = coap_make_str_const("test"); |
61 | 28 | coap_resource_t *resource = coap_resource_init(uri, 0); |
62 | 28 | if (resource) { |
63 | 28 | coap_add_resource(ctx, resource); |
64 | 28 | } |
65 | | |
66 | 28 | unsigned int block_szx = (size > 1) ? (data[1] % 7) : 2; |
67 | 28 | size_t data_len = ((data[2] % 32) + 1) * 64; |
68 | 28 | if (data_len > sizeof(test_data)) { |
69 | 0 | data_len = sizeof(test_data); |
70 | 0 | } |
71 | 28 | uint32_t block_num = (size > 4) ? (data[4] % 16) : 0; |
72 | | |
73 | | /* Populate lg_xmit so timeout functions iterate a non-empty list */ |
74 | 28 | { |
75 | 28 | uint32_t saved_mode = session->block_mode; |
76 | 28 | session->block_mode |= COAP_BLOCK_USE_LIBCOAP; |
77 | 28 | coap_pdu_t *setup_pdu = coap_pdu_init(COAP_MESSAGE_CON, COAP_REQUEST_CODE_PUT, |
78 | 28 | coap_new_message_id(session), |
79 | 28 | coap_session_max_pdu_size(session)); |
80 | 28 | if (setup_pdu) { |
81 | 28 | coap_add_option(setup_pdu, COAP_OPTION_URI_PATH, 4, (const uint8_t *)"test"); |
82 | 28 | coap_add_data_large_request_lkd(session, setup_pdu, sizeof(test_data), |
83 | 28 | test_data, NULL, NULL); |
84 | 28 | coap_delete_pdu(setup_pdu); |
85 | 28 | } |
86 | 28 | session->block_mode = saved_mode; |
87 | 28 | } |
88 | | |
89 | 28 | coap_tick_t now, tim_rem; |
90 | 28 | coap_ticks(&now); |
91 | | |
92 | | /* Timeout handlers */ |
93 | 28 | coap_block_check_lg_xmit_timeouts(session, now, &tim_rem); |
94 | 28 | coap_block_check_lg_crcv_timeouts(session, now, &tim_rem); |
95 | 28 | coap_block_check_lg_srcv_timeouts(session, now, &tim_rem); |
96 | 28 | coap_block_check_q_block1_xmit(session, now, &tim_rem); |
97 | 28 | coap_block_check_q_block2_xmit(session, now, &tim_rem); |
98 | | |
99 | | /* Low-level block encoding */ |
100 | 28 | coap_pdu_t *pdu = coap_pdu_init(COAP_MESSAGE_CON, COAP_REQUEST_CODE_PUT, |
101 | 28 | coap_new_message_id(session), |
102 | 28 | coap_session_max_pdu_size(session)); |
103 | 28 | if (pdu) { |
104 | 28 | coap_add_option(pdu, COAP_OPTION_URI_PATH, 4, (const uint8_t *)"test"); |
105 | | |
106 | 28 | if (coap_add_block(pdu, data_len, test_data, block_num, block_szx)) { |
107 | 17 | coap_block_t block; |
108 | 17 | memset(&block, 0, sizeof(block)); |
109 | 17 | block.num = block_num; |
110 | 17 | block.szx = block_szx; |
111 | 17 | block.m = (size > 5) ? (data[5] & 0x01) : 0; |
112 | 17 | coap_write_block_opt(&block, COAP_OPTION_BLOCK1, pdu, data_len); |
113 | 17 | } |
114 | | |
115 | 28 | coap_block_t block_read; |
116 | 28 | if (coap_get_block(pdu, COAP_OPTION_BLOCK1, &block_read)) { |
117 | 17 | (void)block_read.num; |
118 | 17 | } |
119 | 28 | coap_delete_pdu(pdu); |
120 | 28 | } |
121 | | |
122 | | /* BERT block encoding */ |
123 | 28 | pdu = coap_pdu_init(COAP_MESSAGE_CON, COAP_REQUEST_CODE_PUT, |
124 | 28 | coap_new_message_id(session), |
125 | 28 | coap_session_max_pdu_size(session)); |
126 | 28 | if (pdu) { |
127 | 28 | coap_block_b_t block_b; |
128 | 28 | memset(&block_b, 0, sizeof(block_b)); |
129 | 28 | block_b.num = (size > 6) ? (data[6] % 32) : 0; |
130 | 28 | block_b.szx = block_szx; |
131 | 28 | block_b.m = (size > 7) ? (data[7] & 0x01) : 0; |
132 | 28 | block_b.aszx = block_szx; |
133 | 28 | coap_write_block_b_opt(session, &block_b, COAP_OPTION_BLOCK1, pdu, |
134 | 28 | data_len); |
135 | | |
136 | 28 | coap_pdu_t *resp = coap_pdu_init(COAP_MESSAGE_ACK, COAP_RESPONSE_CODE(205), |
137 | 28 | coap_new_message_id(session), 1152); |
138 | 28 | if (resp) { |
139 | 28 | coap_add_block_b_data(resp, data_len, test_data, &block_b); |
140 | 28 | coap_delete_pdu(resp); |
141 | 28 | } |
142 | 28 | coap_delete_pdu(pdu); |
143 | 28 | } |
144 | | |
145 | | /* Large data transfer APIs */ |
146 | 28 | pdu = coap_pdu_init(COAP_MESSAGE_CON, COAP_REQUEST_CODE_GET, |
147 | 28 | coap_new_message_id(session), |
148 | 28 | coap_session_max_pdu_size(session)); |
149 | 28 | if (pdu && resource) { |
150 | 28 | coap_add_option(pdu, COAP_OPTION_URI_PATH, 4, (const uint8_t *)"test"); |
151 | | |
152 | 28 | coap_pdu_t *resp = coap_pdu_init(COAP_MESSAGE_ACK, COAP_RESPONSE_CODE(205), |
153 | 28 | coap_new_message_id(session), |
154 | 28 | coap_session_max_pdu_size(session)); |
155 | 28 | if (resp) { |
156 | 28 | coap_add_data_large_response(resource, session, pdu, resp, |
157 | 28 | NULL, COAP_MEDIATYPE_TEXT_PLAIN, -1, 0, |
158 | 28 | data_len, test_data, NULL, NULL); |
159 | | |
160 | 28 | coap_pdu_t *resp2 = coap_pdu_init(COAP_MESSAGE_ACK, |
161 | 28 | COAP_RESPONSE_CODE(205), |
162 | 28 | coap_new_message_id(session), 1152); |
163 | 28 | if (resp2) { |
164 | 28 | coap_add_data_blocked_response(pdu, resp2, COAP_MEDIATYPE_TEXT_PLAIN, |
165 | 28 | -1, data_len, test_data); |
166 | 28 | coap_delete_pdu(resp2); |
167 | 28 | } |
168 | 28 | coap_delete_pdu(resp); |
169 | 28 | } |
170 | 28 | coap_delete_pdu(pdu); |
171 | 28 | } |
172 | | |
173 | | /* Large request with lock */ |
174 | 28 | pdu = coap_pdu_init(COAP_MESSAGE_CON, COAP_REQUEST_CODE_PUT, |
175 | 28 | coap_new_message_id(session), |
176 | 28 | coap_session_max_pdu_size(session)); |
177 | 28 | if (pdu) { |
178 | 28 | coap_add_option(pdu, COAP_OPTION_URI_PATH, 4, (const uint8_t *)"test"); |
179 | 28 | coap_add_data_large_request_lkd(session, pdu, data_len, test_data, NULL, |
180 | 28 | NULL); |
181 | 28 | coap_delete_pdu(pdu); |
182 | 28 | } |
183 | | |
184 | | /* Q-Block support check */ |
185 | 28 | (void)coap_q_block_is_supported(); |
186 | | |
187 | | /* Observe cancellation */ |
188 | 28 | pdu = coap_pdu_init(COAP_MESSAGE_CON, COAP_REQUEST_CODE_GET, |
189 | 28 | coap_new_message_id(session), |
190 | 28 | coap_session_max_pdu_size(session)); |
191 | 28 | if (pdu) { |
192 | 28 | coap_add_option(pdu, COAP_OPTION_OBSERVE, 0, NULL); |
193 | | |
194 | 28 | uint8_t token_buf[8]; |
195 | 28 | coap_binary_t token; |
196 | 28 | token.length = (size > 8) ? ((data[8] % 8) + 1) : 1; |
197 | 28 | if (token.length > sizeof(token_buf)) { |
198 | 0 | token.length = sizeof(token_buf); |
199 | 0 | } |
200 | 28 | memcpy(token_buf, (size > 16) ? (data + 12) : data, token.length); |
201 | 28 | token.s = token_buf; |
202 | | |
203 | 28 | coap_cancel_observe(session, &token, COAP_MESSAGE_CON); |
204 | 28 | coap_cancel_observe_lkd(session, &token, COAP_MESSAGE_CON); |
205 | 28 | coap_delete_pdu(pdu); |
206 | 28 | } |
207 | | |
208 | | /* Lifecycle cleanup */ |
209 | 28 | coap_block_delete_lg_crcv(session, NULL); |
210 | 28 | coap_block_delete_lg_xmit(session, NULL); |
211 | 28 | coap_register_block_data_handler(ctx, NULL); |
212 | | |
213 | 28 | coap_io_process(ctx, 1); |
214 | 28 | coap_free_context(ctx); |
215 | 28 | coap_cleanup(); |
216 | | |
217 | 28 | return 0; |
218 | 28 | } |