/src/libcoap/tests/oss-fuzz/block_target.c
Line | Count | Source |
1 | | #include "coap3/coap_internal.h" |
2 | | #include "coap_fuzz_helper.h" |
3 | | #include <stdint.h> |
4 | | #include <string.h> |
5 | | #include <stdlib.h> |
6 | | |
7 | | static int |
8 | 33 | fuzz_event_handler(coap_session_t *session, const coap_event_t event) { |
9 | 33 | (void)session; |
10 | 33 | (void)event; |
11 | 33 | return 0; |
12 | 33 | } |
13 | | |
14 | | /* Resource handler - exercises coap_add_data_large_response() */ |
15 | | static void |
16 | | block_handler(coap_resource_t *resource, coap_session_t *session, |
17 | | const coap_pdu_t *request, const coap_string_t *query, |
18 | 37 | coap_pdu_t *response) { |
19 | 37 | (void)query; |
20 | 37 | size_t len; |
21 | 37 | const uint8_t *databuf; |
22 | | |
23 | 37 | response->code = COAP_RESPONSE_CODE(205); |
24 | | |
25 | 37 | if (coap_get_data(request, &len, &databuf) && len > 64) { |
26 | | /* Large payload - use block transfer API */ |
27 | 6 | coap_add_data_large_response(resource, session, request, response, |
28 | 6 | query, COAP_MEDIATYPE_TEXT_PLAIN, -1, 0, |
29 | 6 | len, databuf, NULL, NULL); |
30 | 31 | } else if (len > 0) { |
31 | 11 | coap_add_data(response, len, databuf); |
32 | 20 | } else { |
33 | | /* Generate 256-byte response to trigger BLOCK2 */ |
34 | 20 | static const uint8_t large_data[256] = { |
35 | 20 | '0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F', |
36 | 20 | '0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F', |
37 | 20 | '0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F', |
38 | 20 | '0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F', |
39 | 20 | '0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F', |
40 | 20 | '0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F', |
41 | 20 | '0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F', |
42 | 20 | '0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F', |
43 | 20 | '0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F', |
44 | 20 | '0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F', |
45 | 20 | '0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F', |
46 | 20 | '0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F', |
47 | 20 | '0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F', |
48 | 20 | '0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F', |
49 | 20 | '0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F', |
50 | 20 | '0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F' |
51 | 20 | }; |
52 | 20 | coap_add_data_large_response(resource, session, request, response, |
53 | 20 | query, COAP_MEDIATYPE_TEXT_PLAIN, -1, 0, |
54 | 20 | sizeof(large_data), large_data, NULL, |
55 | 20 | NULL); |
56 | 20 | } |
57 | 37 | } |
58 | | |
59 | | int |
60 | 77 | LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { |
61 | 77 | coap_context_t *ctx = NULL; |
62 | 77 | coap_session_t *session = NULL; |
63 | 77 | coap_resource_t *resource = NULL; |
64 | 77 | coap_address_t addr; |
65 | | |
66 | 77 | if (size < 8) |
67 | 4 | return 0; |
68 | | |
69 | 73 | coap_startup(); |
70 | 73 | coap_set_log_level(COAP_LOG_EMERG); |
71 | 73 | coap_debug_set_packet_loss("50%"); |
72 | 73 | coap_debug_set_packet_fail("100%"); |
73 | | |
74 | 73 | ctx = coap_new_context(NULL); |
75 | 73 | if (!ctx) |
76 | 0 | goto cleanup; |
77 | 73 | coap_register_event_handler(ctx, fuzz_event_handler); |
78 | | |
79 | | /* Configure block mode and max block size */ |
80 | 73 | uint32_t block_mode = ((uint32_t)data[0] << 8) | data[1]; |
81 | 73 | coap_context_set_block_mode(ctx, block_mode & 0x0F); |
82 | | |
83 | 73 | uint16_t max_block = ((uint16_t)data[2] << 8) | data[3]; |
84 | 73 | if (max_block >= 16 && max_block <= 1024) { |
85 | 36 | coap_context_set_max_block_size(ctx, max_block); |
86 | 36 | } |
87 | | |
88 | | /* Create resource with type and interface attributes */ |
89 | 73 | resource = coap_resource_init(coap_make_str_const("data"), 0); |
90 | 73 | if (resource) { |
91 | 73 | coap_register_request_handler(resource, COAP_REQUEST_GET, block_handler); |
92 | 73 | coap_register_request_handler(resource, COAP_REQUEST_PUT, block_handler); |
93 | 73 | coap_register_request_handler(resource, COAP_REQUEST_POST, block_handler); |
94 | 73 | coap_add_attr(resource, coap_make_str_const("rt"), |
95 | 73 | coap_make_str_const("\"test\""), 0); |
96 | 73 | coap_add_attr(resource, coap_make_str_const("if"), |
97 | 73 | coap_make_str_const("\"block\""), 0); |
98 | 73 | coap_add_resource(ctx, resource); |
99 | 73 | } |
100 | | |
101 | | /* Create session */ |
102 | 73 | coap_address_init(&addr); |
103 | 73 | addr.addr.sa.sa_family = AF_INET; |
104 | 73 | session = coap_new_client_session(ctx, NULL, &addr, COAP_PROTO_UDP); |
105 | 73 | if (!session) |
106 | 0 | goto cleanup; |
107 | 73 | session->state = COAP_SESSION_STATE_ESTABLISHED; |
108 | | |
109 | | /* Dispatch with programmatic PDU and raw wire format */ |
110 | 73 | coap_fuzz_dispatch(ctx, session, data, size, (const uint8_t *)"data", 4); |
111 | | |
112 | | /* Probe .well-known/core with a fuzz-derived query filter */ |
113 | 73 | { |
114 | 73 | coap_pdu_t *wk = coap_pdu_init(COAP_MESSAGE_CON, COAP_REQUEST_CODE_GET, |
115 | 73 | coap_new_message_id(session), |
116 | 73 | coap_session_max_pdu_size(session)); |
117 | 73 | if (wk) { |
118 | 73 | coap_add_option(wk, COAP_OPTION_URI_PATH, 11, |
119 | 73 | (const uint8_t *)".well-known"); |
120 | 73 | coap_add_option(wk, COAP_OPTION_URI_PATH, 4, |
121 | 73 | (const uint8_t *)"core"); |
122 | 73 | uint8_t qlen = (data[4] % 16) + 1; |
123 | 73 | if ((size_t)5 + qlen <= size) |
124 | 47 | coap_add_option(wk, COAP_OPTION_URI_QUERY, qlen, data + 5); |
125 | 73 | coap_lock_lock(goto cleanup); |
126 | 73 | coap_dispatch(ctx, session, wk); |
127 | 73 | coap_lock_unlock(); |
128 | 73 | coap_delete_pdu(wk); |
129 | 73 | } |
130 | 73 | } |
131 | | |
132 | 73 | cleanup: |
133 | 73 | if (session) |
134 | 73 | coap_session_release(session); |
135 | 73 | if (ctx) |
136 | 73 | coap_free_context(ctx); |
137 | 73 | coap_cleanup(); |
138 | 73 | return 0; |
139 | 73 | } |