Coverage Report

Created: 2026-09-01 07:10

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libcoap/tests/oss-fuzz/network_message_target.c
Line
Count
Source
1
#include "coap3/coap_internal.h"
2
#include <stdlib.h>
3
#include <string.h>
4
5
/* Test UDP datagram dispatch and message handling */
6
static void
7
test_dgram_dispatch(coap_context_t *ctx, coap_session_t *session,
8
2.88k
                    uint8_t *data, size_t size) {
9
2.88k
  if (!ctx || !session || !data || size < 4) {
10
0
    return;
11
0
  }
12
13
2.88k
  session->state = COAP_SESSION_STATE_ESTABLISHED;
14
2.88k
  coap_lock_lock(return);
15
2.88k
  coap_handle_dgram(ctx, session, data, size);
16
2.88k
  coap_lock_unlock();
17
2.88k
}
18
19
/* Test retransmission queue operations (coap_wait_ack, peek_next, pop_next) */
20
static void
21
test_queue_operations(coap_context_t *ctx, coap_session_t *session,
22
1.89k
                      const uint8_t *data, size_t size) {
23
1.89k
  if (!ctx || !session || size < 8) {
24
0
    return;
25
0
  }
26
27
1.89k
  coap_pdu_t *pdu = coap_pdu_init(COAP_MESSAGE_CON,
28
1.89k
                                  COAP_REQUEST_CODE_GET,
29
1.89k
                                  coap_new_message_id(session),
30
1.89k
                                  64);
31
1.89k
  if (!pdu) {
32
0
    return;
33
0
  }
34
35
1.89k
  size_t token_len = (data[0] % 8) + 1;
36
1.89k
  if (token_len <= size) {
37
1.89k
    coap_add_token(pdu, token_len, data);
38
1.89k
  }
39
40
1.89k
  coap_queue_t *node = coap_new_node();
41
1.89k
  if (node) {
42
1.89k
    node->session = session;
43
1.89k
    node->pdu = pdu;
44
1.89k
    node->id = pdu->mid;
45
1.89k
    node->timeout = 1000;
46
47
1.89k
    coap_wait_ack(ctx, session, node);
48
49
1.89k
    coap_queue_t *peek = coap_peek_next(ctx);
50
1.89k
    if (peek) {
51
1.89k
      (void)peek;
52
1.89k
    }
53
54
1.89k
    coap_queue_t *popped = coap_pop_next(ctx);
55
1.89k
    if (popped) {
56
1.89k
      coap_delete_node(popped);
57
1.89k
    }
58
1.89k
  } else {
59
0
    coap_delete_pdu(pdu);
60
0
  }
61
1.89k
}
62
63
/* Test TCP transport and CSM signaling */
64
static void
65
test_reliable_transport(coap_context_t *ctx, coap_session_t *session,
66
1.89k
                        uint8_t *data, size_t size) {
67
1.89k
  if (!ctx || !session || !data || size < 8) {
68
0
    return;
69
0
  }
70
71
1.89k
  session->proto = COAP_PROTO_TCP;
72
1.89k
  session->state = COAP_SESSION_STATE_ESTABLISHED;
73
1.89k
  session->type = COAP_SESSION_TYPE_CLIENT;
74
75
1.89k
  coap_pdu_t *pdu = coap_pdu_init(COAP_MESSAGE_CON,
76
1.89k
                                  COAP_SIGNALING_CODE_CSM,
77
1.89k
                                  0,
78
1.89k
                                  64);
79
1.89k
  if (!pdu) {
80
0
    return;
81
0
  }
82
83
1.89k
  if (size >= 4) {
84
1.89k
    uint32_t max_msg_size = ((uint32_t)data[0] << 24) |
85
1.89k
                            ((uint32_t)data[1] << 16) |
86
1.89k
                            ((uint32_t)data[2] << 8) |
87
1.89k
                            (uint32_t)data[3];
88
1.89k
    if (max_msg_size >= 64) {
89
1.85k
      uint8_t buf[4];
90
1.85k
      coap_insert_option(pdu, (coap_option_num_t)COAP_SIG_OPT_MAX_MESSAGE_SIZE,
91
1.85k
                         coap_encode_var_safe(buf, sizeof(buf), max_msg_size),
92
1.85k
                         buf);
93
1.85k
    }
94
1.89k
  }
95
96
1.89k
  coap_dispatch(ctx, session, pdu);
97
98
1.89k
  coap_delete_pdu(pdu);
99
1.89k
}
100
101
/* Test session state transitions and send operations */
102
static void
103
test_session_operations(coap_context_t *ctx, coap_session_t *session,
104
1.89k
                        const uint8_t *data, size_t size) {
105
1.89k
  if (!ctx || !session || !data || size < 16) {
106
0
    return;
107
0
  }
108
109
1.89k
  coap_session_state_t states[] = {
110
1.89k
    COAP_SESSION_STATE_NONE,
111
1.89k
    COAP_SESSION_STATE_CONNECTING,
112
1.89k
    COAP_SESSION_STATE_HANDSHAKE,
113
1.89k
    COAP_SESSION_STATE_CSM,
114
1.89k
    COAP_SESSION_STATE_ESTABLISHED
115
1.89k
  };
116
117
1.89k
  session->state = states[data[0] % 5];
118
119
1.89k
  coap_pdu_t *pdu = coap_pdu_init(COAP_MESSAGE_CON,
120
1.89k
                                  COAP_REQUEST_CODE_GET,
121
1.89k
                                  coap_new_message_id(session),
122
1.89k
                                  128);
123
1.89k
  if (!pdu) {
124
0
    return;
125
0
  }
126
127
1.89k
  size_t token_len = (data[1] % 8) + 1;
128
1.89k
  if (token_len + 2 <= size) {
129
1.89k
    coap_add_token(pdu, token_len, &data[2]);
130
1.89k
  }
131
132
1.89k
  if (size >= token_len + 10) {
133
1.86k
    size_t path_len = (data[token_len + 2] % 16) + 1;
134
1.86k
    if (token_len + 2 + path_len + 1 <= size) {
135
1.79k
      coap_add_option(pdu, COAP_OPTION_URI_PATH, path_len,
136
1.79k
                      &data[token_len + 3]);
137
1.79k
    }
138
1.86k
  }
139
140
1.89k
  if (session->state == COAP_SESSION_STATE_ESTABLISHED) {
141
337
    coap_send_ack(session, pdu);
142
337
    coap_send_rst(session, pdu);
143
144
337
    if (COAP_PDU_IS_REQUEST(pdu)) {
145
337
      coap_send_error(session, pdu, COAP_RESPONSE_CODE(400), NULL);
146
337
      coap_send_error(session, pdu, COAP_RESPONSE_CODE(404), NULL);
147
337
      coap_send_error(session, pdu, COAP_RESPONSE_CODE(500), NULL);
148
337
    }
149
337
  }
150
151
1.89k
  coap_delete_pdu(pdu);
152
1.89k
}
153
154
/* Test context configuration */
155
static void
156
1.89k
test_context_config(coap_context_t *ctx, const uint8_t *data, size_t size) {
157
1.89k
  if (!ctx || size < 16) {
158
0
    return;
159
0
  }
160
161
  /* Use fuzz data to configure various context parameters */
162
1.89k
  coap_context_set_keepalive(ctx, data[0]);
163
1.89k
  coap_context_set_max_idle_sessions(ctx, data[1]);
164
1.89k
  coap_context_set_max_handshake_sessions(ctx, data[2]);
165
1.89k
  coap_context_set_session_timeout(ctx, data[3]);
166
1.89k
  size_t token_size = 8 + (data[4] % 256);
167
1.89k
  coap_context_set_max_token_size(ctx, token_size);
168
169
1.89k
  if (size >= 20) {
170
1.74k
    size_t csm_max_message_size = ((uint32_t)data[16] << 24) | (data[17] << 16) |
171
1.74k
                                  (data[18] << 8) | data[19];
172
1.74k
    if (csm_max_message_size >= 64) {
173
1.38k
      coap_context_set_csm_max_message_size(ctx, csm_max_message_size);
174
1.38k
    }
175
176
1.74k
    uint32_t timeout = ((uint32_t)data[12] << 24) | (data[13] << 16) |
177
1.74k
                       (data[14] << 8) | data[15];
178
1.74k
    coap_context_set_csm_timeout_ms(ctx, timeout);
179
1.74k
  }
180
1.89k
}
181
182
/* Test PSK (Pre-Shared Key) configuration */
183
static void
184
1.14k
test_psk_config(coap_context_t *ctx, const uint8_t *data, size_t size) {
185
1.14k
  if (!ctx || size < 32) {
186
0
    return;
187
0
  }
188
189
  /* Extract key and hint lengths from fuzz data */
190
1.14k
  size_t key_len = (data[0] % 16) + 1;
191
1.14k
  size_t hint_len = (data[1] % 16) + 1;
192
193
1.14k
  if (size >= 32 + key_len + hint_len) {
194
1.06k
    char *hint = malloc(hint_len + 1);
195
1.06k
    if (!hint) {
196
0
      return;
197
0
    }
198
1.06k
    memcpy(hint, &data[2], hint_len);
199
1.06k
    hint[hint_len] = '\0';
200
201
1.06k
    const uint8_t *key = &data[2 + hint_len];
202
1.06k
    coap_context_set_psk(ctx, hint, key, key_len);
203
204
1.06k
    free(hint);
205
1.06k
  }
206
1.14k
}
207
208
int
209
2.93k
LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
210
2.93k
  coap_context_t *ctx = NULL;
211
2.93k
  coap_session_t *session = NULL;
212
2.93k
  coap_address_t local_addr, remote_addr;
213
2.93k
  uint8_t *data_copy = NULL;
214
215
2.93k
  if (size < 8) {
216
4
    return 0;
217
4
  }
218
219
  /* Create writable copy of input data */
220
2.93k
  data_copy = malloc(size);
221
2.93k
  if (!data_copy) {
222
0
    return 0;
223
0
  }
224
2.93k
  memcpy(data_copy, data, size);
225
226
  /* Initialize CoAP library */
227
2.93k
  coap_startup();
228
2.93k
  coap_set_log_level(COAP_LOG_EMERG);
229
2.93k
  coap_debug_set_packet_loss("50%");
230
2.93k
  coap_debug_set_packet_fail("100%");
231
232
  /* Setup local address */
233
2.93k
  coap_address_init(&local_addr);
234
2.93k
  local_addr.addr.sa.sa_family = AF_INET;
235
236
  /* Create CoAP context */
237
2.93k
  ctx = coap_new_context(NULL);
238
2.93k
  if (!ctx) {
239
0
    goto cleanup;
240
0
  }
241
242
  /* Test context configuration if enough data */
243
2.93k
  if (size >= 16) {
244
1.89k
    test_context_config(ctx, data, size);
245
1.89k
  }
246
247
  /* Create client session for testing */
248
2.93k
  coap_address_init(&remote_addr);
249
2.93k
  remote_addr.addr.sa.sa_family = AF_INET;
250
2.93k
  memcpy(&remote_addr.addr.sin.sin_addr.s_addr,
251
2.93k
         &data[size > 4 ? size - 4 : 0],
252
2.93k
         size > 4 ? 4 : size);
253
2.93k
  remote_addr.addr.sin.sin_port = htons(5683);
254
255
2.93k
  coap_proto_t proto = COAP_PROTO_UDP;
256
2.93k
  if (size >= 2) {
257
2.93k
    if (data[0] & 0x10) {
258
10
      proto = COAP_PROTO_TCP;
259
10
#if !COAP_DISABLE_TCP
260
2.92k
    } else if (data[0] & 0x08) {
261
40
      proto = COAP_PROTO_DTLS;
262
40
#endif
263
40
    }
264
2.93k
  }
265
266
2.93k
  session = coap_new_client_session(ctx, NULL, &remote_addr, proto);
267
2.93k
  if (!session) {
268
1
    goto cleanup;
269
1
  }
270
271
2.93k
  if (size >= 8 && session->proto == COAP_PROTO_UDP) {
272
2.88k
    size_t msg_offset = size >= 16 ? 8 : 4;
273
2.88k
    size_t msg_len = size - msg_offset;
274
2.88k
    if (msg_len >= 4) {
275
2.88k
      test_dgram_dispatch(ctx, session, data_copy + msg_offset, msg_len);
276
2.88k
    }
277
2.88k
  }
278
279
2.93k
  if (size >= 16) {
280
1.89k
    test_queue_operations(ctx, session, data + 1, size - 1);
281
1.89k
  }
282
283
2.93k
#if !COAP_DISABLE_TCP
284
2.93k
  if (size >= 16) {
285
1.89k
    test_reliable_transport(ctx, session, data_copy + 4, size - 4);
286
1.89k
  }
287
2.93k
#endif
288
289
2.93k
  if (size >= 16) {
290
1.89k
    test_session_operations(ctx, session, data, size);
291
1.89k
  }
292
293
2.93k
  if (size >= 32) {
294
1.14k
    test_psk_config(ctx, data, size);
295
1.14k
  }
296
297
2.93k
cleanup:
298
2.93k
  if (session) {
299
2.93k
    coap_session_release(session);
300
2.93k
  }
301
2.93k
  if (ctx) {
302
2.93k
    coap_free_context(ctx);
303
2.93k
  }
304
2.93k
  if (data_copy) {
305
2.93k
    free(data_copy);
306
2.93k
  }
307
2.93k
  coap_cleanup();
308
309
2.93k
  return 0;
310
2.93k
}