Coverage Report

Created: 2026-08-13 07:06

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libcoap/tests/oss-fuzz/coap_fuzz_helper.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
/* Wrapping byte reader to ensure never goes out of bounds */
8
typedef struct {
9
  const uint8_t *data;
10
  size_t size;
11
  size_t pos;
12
} coap_fuzz_cursor_t;
13
static inline uint8_t
14
1.54k
coap_fuzz_u8(coap_fuzz_cursor_t *c) {
15
1.54k
  return c->size ? c->data[c->pos++ % c->size] : 0;
16
1.54k
}
17
18
/* All 7 request codes */
19
static const coap_pdu_code_t coap_fuzz_req_codes[] = {
20
  COAP_REQUEST_CODE_GET,    COAP_REQUEST_CODE_POST,   COAP_REQUEST_CODE_PUT,
21
  COAP_REQUEST_CODE_DELETE, COAP_REQUEST_CODE_FETCH,
22
  COAP_REQUEST_CODE_IPATCH, COAP_REQUEST_CODE_PATCH,
23
};
24
25
/* Options reachable after a fixed path anchor */
26
static const uint16_t coap_fuzz_opt_nums[] = {
27
  COAP_OPTION_CONTENT_FORMAT, COAP_OPTION_MAXAGE,  COAP_OPTION_URI_QUERY,
28
  COAP_OPTION_ACCEPT,         COAP_OPTION_BLOCK2,  COAP_OPTION_BLOCK1,
29
  COAP_OPTION_SIZE1,          COAP_OPTION_ECHO,    COAP_OPTION_NORESPONSE,
30
};
31
154
#define COAP_FUZZ_OPT_N 9
32
33
void
34
coap_fuzz_dispatch(coap_context_t *ctx, coap_session_t *session,
35
                   const uint8_t *data, size_t size,
36
141
                   const uint8_t *fixed_path, size_t fixed_path_len) {
37
141
  if (!ctx || !session || !data || size < 4)
38
5
    return;
39
40
  /* Programmatic PDU with fixed URI-Path using coap_dispatch() */
41
136
  {
42
136
    coap_fuzz_cursor_t c = { data, size, 0 };
43
136
    coap_pdu_type_t type = coap_fuzz_u8(&c) & 1 ? COAP_MESSAGE_NON : COAP_MESSAGE_CON;
44
136
    coap_pdu_code_t code = coap_fuzz_req_codes[coap_fuzz_u8(&c) % 7];
45
136
    uint8_t tkl = coap_fuzz_u8(&c) % 9, token[8];
46
478
    for (uint8_t i = 0; i < tkl; i++)
47
342
      token[i] = coap_fuzz_u8(&c);
48
49
136
    coap_pdu_t *pdu = coap_pdu_init(type, code, coap_new_message_id(session),
50
136
                                    coap_session_max_pdu_size(session));
51
136
    if (pdu) {
52
136
      if (tkl)
53
95
        coap_add_token(pdu, tkl, token);
54
55
136
      uint16_t last = 0;
56
136
      if (fixed_path && fixed_path_len) {
57
136
        coap_add_option(pdu, COAP_OPTION_URI_PATH, fixed_path_len, fixed_path);
58
136
        last = COAP_OPTION_URI_PATH;
59
136
      }
60
61
136
      uint8_t n = coap_fuzz_u8(&c) % 4;
62
290
      for (uint8_t i = 0; i < n; i++) {
63
154
        uint16_t opt = coap_fuzz_opt_nums[coap_fuzz_u8(&c) % COAP_FUZZ_OPT_N];
64
154
        if (opt <= last)
65
42
          continue;
66
112
        uint8_t vlen = coap_fuzz_u8(&c) % 9, vbuf[8];
67
508
        for (uint8_t j = 0; j < vlen; j++)
68
396
          vbuf[j] = coap_fuzz_u8(&c);
69
112
        if (coap_add_option(pdu, opt, vlen, vbuf))
70
60
          last = opt;
71
112
      }
72
73
136
      size_t rem = c.pos < size ? size - c.pos : 0;
74
136
      if (rem) {
75
85
        size_t avail = coap_session_max_pdu_size(session) - pdu->used_size - 1;
76
85
        coap_add_data(pdu, rem < avail ? rem : avail, data + c.pos);
77
85
      }
78
79
136
      coap_lock_lock(return);
80
136
      coap_dispatch(ctx, session, pdu);
81
136
      coap_lock_unlock();
82
136
      coap_delete_pdu(pdu);
83
136
    }
84
136
  }
85
86
  /* Raw wire format using coap_handle_dgram() */
87
136
  {
88
136
    uint8_t *copy = malloc(size);
89
136
    if (copy) {
90
136
      memcpy(copy, data, size);
91
136
      coap_lock_lock(return);
92
136
      coap_handle_dgram(ctx, session, copy, size);
93
136
      coap_lock_unlock();
94
136
      free(copy);
95
136
    }
96
136
  }
97
136
}