/src/libcoap/tests/oss-fuzz/async_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 | 22 | fuzz_event_handler(coap_session_t *session, const coap_event_t event) { |
9 | 22 | (void)session; |
10 | 22 | (void)event; |
11 | 22 | return 0; |
12 | 22 | } |
13 | | |
14 | | static void |
15 | | async_handler(coap_resource_t *resource, coap_session_t *session, |
16 | | const coap_pdu_t *request, const coap_string_t *query, |
17 | 12 | coap_pdu_t *response) { |
18 | 12 | (void)resource; |
19 | 12 | (void)query; |
20 | | |
21 | 12 | size_t len; |
22 | 12 | const uint8_t *databuf; |
23 | 12 | coap_bin_const_t token = coap_pdu_get_token(request); |
24 | 12 | coap_async_t *async = coap_find_async(session, token); |
25 | | |
26 | 12 | if (async) { |
27 | 0 | response->code = COAP_RESPONSE_CODE(205); |
28 | 0 | if (coap_get_data(request, &len, &databuf) && len > 0) { |
29 | 0 | coap_add_data(response, len, databuf); |
30 | 0 | } |
31 | 0 | coap_free_async(session, async); |
32 | 12 | } else { |
33 | 12 | response->code = COAP_RESPONSE_CODE(400); |
34 | 12 | if (coap_get_data(request, &len, &databuf) && len > 0) { |
35 | 10 | async = coap_register_async(session, request, |
36 | 10 | (coap_tick_t)len * COAP_TICKS_PER_SECOND / 100); |
37 | 10 | if (async && len > 1) { |
38 | 9 | uint8_t *app_data = malloc(len); |
39 | 9 | if (app_data) { |
40 | 9 | memcpy(app_data, databuf, len); |
41 | 9 | coap_async_set_app_data2(async, app_data, free); |
42 | 9 | response->code = COAP_RESPONSE_CODE(0); |
43 | 9 | } |
44 | 9 | } |
45 | 10 | } |
46 | 12 | } |
47 | 12 | } |
48 | | |
49 | | int |
50 | 37 | LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { |
51 | 37 | coap_context_t *ctx = NULL; |
52 | 37 | coap_session_t *session = NULL; |
53 | 37 | coap_resource_t *resource = NULL; |
54 | 37 | coap_address_t addr; |
55 | 37 | coap_pdu_t *pdu = NULL; |
56 | | |
57 | 37 | if (size < 16) |
58 | 6 | return 0; |
59 | | |
60 | 31 | coap_startup(); |
61 | 31 | coap_set_log_level(COAP_LOG_EMERG); |
62 | 31 | coap_debug_set_packet_loss("50%"); |
63 | 31 | coap_debug_set_packet_fail("100%"); |
64 | | |
65 | 31 | ctx = coap_new_context(NULL); |
66 | 31 | if (!ctx) |
67 | 0 | goto cleanup; |
68 | 31 | coap_register_event_handler(ctx, fuzz_event_handler); |
69 | | |
70 | 31 | resource = coap_resource_init(coap_make_str_const("async"), 0); |
71 | 31 | if (resource) { |
72 | 31 | coap_register_request_handler(resource, COAP_REQUEST_GET, async_handler); |
73 | 31 | coap_register_request_handler(resource, COAP_REQUEST_POST, async_handler); |
74 | 31 | coap_add_resource(ctx, resource); |
75 | 31 | } |
76 | | |
77 | 31 | coap_address_init(&addr); |
78 | 31 | addr.addr.sin.sin_family = AF_INET; |
79 | 31 | addr.addr.sin.sin_port = htons(5683); |
80 | 31 | addr.addr.sin.sin_addr.s_addr = htonl(0x7F000001); |
81 | | |
82 | 31 | session = coap_new_client_session(ctx, NULL, &addr, COAP_PROTO_UDP); |
83 | 31 | if (!session) |
84 | 0 | goto cleanup; |
85 | 31 | session->state = COAP_SESSION_STATE_ESTABLISHED; |
86 | | |
87 | | /* Direct async API testing */ |
88 | 31 | size_t token_len = (size > 8) ? 8 : size; |
89 | 31 | pdu = coap_pdu_init(COAP_MESSAGE_CON, COAP_REQUEST_CODE_GET, |
90 | 31 | coap_new_message_id(session), 128); |
91 | 31 | if (pdu) { |
92 | 31 | coap_add_token(pdu, token_len, data); |
93 | 31 | coap_add_option(pdu, COAP_OPTION_URI_PATH, 5, (const uint8_t *)"async"); |
94 | | |
95 | 31 | coap_async_t *async = coap_register_async(session, pdu, |
96 | 31 | COAP_TICKS_PER_SECOND); |
97 | 31 | if (async) { |
98 | 31 | coap_bin_const_t token = {.length = token_len, .s = data}; |
99 | 31 | coap_async_t *found = coap_find_async(session, token); |
100 | | |
101 | 31 | if (found && size > token_len) { |
102 | 31 | coap_async_set_delay(async, COAP_TICKS_PER_SECOND / 10); |
103 | 31 | coap_async_trigger(async); |
104 | | |
105 | | /* Test app data operations */ |
106 | 31 | coap_async_get_app_data(async); |
107 | 31 | } |
108 | | |
109 | 31 | coap_free_async(session, async); |
110 | 31 | } |
111 | 31 | coap_delete_pdu(pdu); |
112 | | |
113 | | /* Test registration failure path */ |
114 | 31 | if (size > 32) { |
115 | 17 | pdu = coap_pdu_init(COAP_MESSAGE_CON, COAP_REQUEST_CODE_POST, |
116 | 17 | coap_new_message_id(session), 64); |
117 | 17 | if (pdu) { |
118 | 17 | coap_add_token(pdu, 4, &data[16]); |
119 | 17 | coap_async_t *async2 = coap_register_async(session, pdu, 0); |
120 | 17 | if (async2) { |
121 | 17 | coap_async_set_delay(async2, COAP_TICKS_PER_SECOND * 2); |
122 | 17 | coap_free_async(session, async2); |
123 | 17 | } |
124 | 17 | coap_delete_pdu(pdu); |
125 | 17 | } |
126 | 17 | } |
127 | 31 | } |
128 | | |
129 | | /* Dispatch with programmatic PDU and raw wire format */ |
130 | 31 | coap_fuzz_dispatch(ctx, session, data, size, (const uint8_t *)"async", 5); |
131 | | |
132 | 31 | cleanup: |
133 | 31 | if (session) |
134 | 31 | coap_session_release(session); |
135 | 31 | if (ctx) |
136 | 31 | coap_free_context(ctx); |
137 | 31 | coap_cleanup(); |
138 | 31 | return 0; |
139 | 31 | } |