/src/libcoap/tests/oss-fuzz/observe_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 | | |
6 | | static int |
7 | 16 | fuzz_event_handler(coap_session_t *session, const coap_event_t event) { |
8 | 16 | (void)session; |
9 | 16 | (void)event; |
10 | 16 | return 0; |
11 | 16 | } |
12 | | |
13 | | static void |
14 | | fuzz_handler(coap_resource_t *resource, coap_session_t *session, |
15 | | const coap_pdu_t *request, const coap_string_t *query, |
16 | 172 | coap_pdu_t *response) { |
17 | 172 | (void)resource; |
18 | 172 | (void)session; |
19 | 172 | (void)request; |
20 | 172 | (void)query; |
21 | 172 | response->code = COAP_RESPONSE_CODE(205); |
22 | 172 | } |
23 | | |
24 | | int |
25 | 34 | LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { |
26 | 34 | if (size < 1) |
27 | 0 | return 0; |
28 | | |
29 | 34 | coap_startup(); |
30 | 34 | coap_set_log_level(COAP_LOG_EMERG); |
31 | 34 | coap_debug_set_packet_loss("50%"); |
32 | 34 | coap_debug_set_packet_fail("100%"); |
33 | | |
34 | 34 | coap_context_t *ctx = coap_new_context(NULL); |
35 | 34 | if (!ctx) |
36 | 0 | goto cleanup; |
37 | 34 | coap_register_event_handler(ctx, fuzz_event_handler); |
38 | | |
39 | 34 | coap_resource_t *res = coap_resource_init(coap_make_str_const("obs"), 0); |
40 | 34 | if (!res) |
41 | 0 | goto cleanup; |
42 | 34 | res->observable = 1; |
43 | 34 | coap_register_request_handler(res, COAP_REQUEST_GET, fuzz_handler); |
44 | 34 | coap_add_resource(ctx, res); |
45 | | |
46 | 34 | coap_address_t addr; |
47 | 34 | coap_address_init(&addr); |
48 | 34 | addr.addr.sa.sa_family = AF_INET; |
49 | 34 | coap_session_t *sess = coap_new_client_session(ctx, NULL, &addr, COAP_PROTO_UDP); |
50 | 34 | if (!sess) |
51 | 0 | goto cleanup; |
52 | 34 | sess->state = COAP_SESSION_STATE_ESTABLISHED; |
53 | | |
54 | | /* Test observer functions with fuzzed data */ |
55 | 34 | size_t offset = 0; |
56 | 34 | int iterations = 0; |
57 | 131 | while (offset + 1 < size && iterations++ < 5) { |
58 | 97 | coap_pdu_t *pdu = coap_pdu_init(COAP_MESSAGE_CON, COAP_REQUEST_CODE_GET, 1, 128); |
59 | 97 | if (!pdu) |
60 | 0 | break; |
61 | | |
62 | | /* Fuzzed token */ |
63 | 97 | size_t tok_len = (data[offset] % 8) + 1; |
64 | 97 | if (offset + tok_len < size) { |
65 | 93 | coap_add_token(pdu, tok_len, data + offset); |
66 | 93 | offset += tok_len; |
67 | 93 | } |
68 | | |
69 | | /* Add Observe option */ |
70 | 97 | uint8_t obs_val = 0; |
71 | 97 | coap_insert_option(pdu, COAP_OPTION_OBSERVE, 1, &obs_val); |
72 | 97 | coap_add_option(pdu, COAP_OPTION_URI_PATH, 3, (const uint8_t *)"obs"); |
73 | | |
74 | | /* Test coap_add_observer */ |
75 | 97 | coap_lock_lock(goto cleanup); |
76 | 97 | coap_subscription_t *sub = coap_add_observer(res, sess, &pdu->actual_token, pdu); |
77 | 97 | coap_lock_unlock(); |
78 | | |
79 | 97 | if (sub) { |
80 | | /* Test coap_find_observer */ |
81 | 97 | coap_find_observer(res, sess, &pdu->actual_token); |
82 | | |
83 | | /* Test coap_touch_observer */ |
84 | 97 | coap_touch_observer(ctx, sess, &pdu->actual_token); |
85 | | |
86 | | /* Test coap_resource_notify_observers*/ |
87 | 97 | coap_resource_notify_observers(res, NULL); |
88 | | |
89 | | /* Test coap_delete_observer */ |
90 | 97 | coap_lock_lock(goto cleanup); |
91 | 97 | coap_delete_observer(res, sess, &pdu->actual_token); |
92 | 97 | coap_lock_unlock(); |
93 | 97 | } |
94 | | |
95 | 97 | coap_delete_pdu(pdu); |
96 | 97 | offset += 8; |
97 | 97 | } |
98 | | |
99 | | /* Dispatch GET+OBSERVE to exercise subscription paths in handle_request */ |
100 | 34 | { |
101 | 34 | uint8_t obs_val; |
102 | 102 | for (obs_val = 0; obs_val <= 1; obs_val++) { |
103 | 68 | coap_pdu_t *op = coap_pdu_init(COAP_MESSAGE_CON, COAP_REQUEST_CODE_GET, |
104 | 68 | coap_new_message_id(sess), 128); |
105 | 68 | if (op) { |
106 | 68 | coap_add_option(op, COAP_OPTION_OBSERVE, 1, &obs_val); |
107 | 68 | coap_add_option(op, COAP_OPTION_URI_PATH, 3, (const uint8_t *)"obs"); |
108 | 68 | coap_lock_lock(goto cleanup); |
109 | 68 | coap_dispatch(ctx, sess, op); |
110 | 68 | coap_lock_unlock(); |
111 | 68 | coap_delete_pdu(op); |
112 | 68 | } |
113 | 68 | } |
114 | 34 | } |
115 | | |
116 | | /* Dispatch with programmatic PDU and raw wire format */ |
117 | 34 | coap_fuzz_dispatch(ctx, sess, data, size, (const uint8_t *)"obs", 3); |
118 | | |
119 | 34 | cleanup: |
120 | 34 | if (ctx) |
121 | 34 | coap_free_context(ctx); |
122 | 34 | coap_cleanup(); |
123 | 34 | return 0; |
124 | 34 | } |