/src/libcoap/tests/oss-fuzz/uri_extended_target.c
Line | Count | Source |
1 | | /* Extended URI parsing fuzzer for libcoap. |
2 | | * |
3 | | * The existing split_uri_target only calls coap_split_uri(). coap_uri.c is |
4 | | * sitting at ~41% line coverage in the public report, so this harness |
5 | | * additionally exercises: |
6 | | * - coap_split_proxy_uri() (proxy-uri scheme path) |
7 | | * - coap_split_path() / coap_path_into_optlist() |
8 | | * - coap_split_query() / coap_query_into_optlist() |
9 | | * - coap_check_dots() (segment dot handling) |
10 | | * - coap_uri_into_optlist() and coap_uri_into_optlist_abbrev() |
11 | | * - coap_new_uri() / coap_clone_uri() / coap_delete_uri() |
12 | | * |
13 | | * All of these consume untrusted byte strings (a URI received over the wire |
14 | | * or via the CoAP Proxy-Uri option) and produce option lists used during |
15 | | * request processing — exactly the kind of code path an attacker controls. |
16 | | */ |
17 | | |
18 | | #include "coap3/coap_internal.h" |
19 | | |
20 | | #include <stdint.h> |
21 | | #include <stdlib.h> |
22 | | #include <string.h> |
23 | | |
24 | | int |
25 | 1.75k | LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { |
26 | 1.75k | if (size < 2 || size > 4096) |
27 | 20 | return 0; |
28 | | |
29 | 1.73k | coap_startup(); |
30 | 1.73k | coap_set_log_level(COAP_LOG_EMERG); |
31 | | |
32 | | /* Use the first byte as a selector so a single corpus entry exercises |
33 | | * multiple entrypoints across iterations. */ |
34 | 1.73k | uint8_t mode = data[0]; |
35 | 1.73k | const uint8_t *buf = data + 1; |
36 | 1.73k | size_t buf_len = size - 1; |
37 | | |
38 | | /* coap_split_proxy_uri — different validation rules than split_uri. */ |
39 | 1.73k | { |
40 | 1.73k | coap_uri_t uri; |
41 | 1.73k | memset(&uri, 0, sizeof(uri)); |
42 | 1.73k | coap_split_proxy_uri(buf, buf_len, &uri); |
43 | 1.73k | } |
44 | | |
45 | | /* coap_split_uri + downstream usage. */ |
46 | 1.73k | coap_uri_t parsed_uri; |
47 | 1.73k | memset(&parsed_uri, 0, sizeof(parsed_uri)); |
48 | 1.73k | int split_ok = coap_split_uri(buf, buf_len, &parsed_uri); |
49 | | |
50 | | /* coap_check_dots on small windows across the buffer to drive its |
51 | | * percent-encoded "." / ".." special cases. */ |
52 | 13.3k | for (size_t i = 0; i + 1 < buf_len && i < 8; i++) { |
53 | 11.6k | size_t window = buf_len - i; |
54 | 11.6k | if (window > 6) |
55 | 9.12k | window = 6; |
56 | 11.6k | coap_check_dots(buf + i, window); |
57 | 11.6k | } |
58 | | |
59 | | /* coap_split_path: writes serialised options into a caller buffer. */ |
60 | 1.73k | { |
61 | 1.73k | unsigned char out[256]; |
62 | 1.73k | size_t out_len = sizeof(out); |
63 | 1.73k | coap_split_path(buf, buf_len, out, &out_len); |
64 | 1.73k | } |
65 | | |
66 | | /* coap_split_query. */ |
67 | 1.73k | { |
68 | 1.73k | unsigned char out[256]; |
69 | 1.73k | size_t out_len = sizeof(out); |
70 | 1.73k | coap_split_query(buf, buf_len, out, &out_len); |
71 | 1.73k | } |
72 | | |
73 | | /* coap_path_into_optlist / coap_query_into_optlist — populate an |
74 | | * optlist chain that we must release. */ |
75 | 1.73k | if (mode & 0x01) { |
76 | 1.50k | coap_optlist_t *chain = NULL; |
77 | 1.50k | coap_path_into_optlist(buf, buf_len, COAP_OPTION_URI_PATH, &chain); |
78 | 1.50k | coap_query_into_optlist(buf, buf_len, COAP_OPTION_URI_QUERY, &chain); |
79 | 1.50k | coap_delete_optlist(chain); |
80 | 1.50k | } |
81 | | |
82 | | /* coap_new_uri / coap_clone_uri exercise the heap-allocated URI path. */ |
83 | 1.73k | if (mode & 0x02) { |
84 | 1.03k | coap_uri_t *u = coap_new_uri(buf, (unsigned int)buf_len); |
85 | 1.03k | if (u) { |
86 | 416 | coap_uri_t *clone = coap_clone_uri(u); |
87 | 416 | coap_delete_uri(clone); |
88 | 416 | coap_delete_uri(u); |
89 | 416 | } |
90 | 1.03k | } |
91 | | |
92 | | /* coap_uri_into_optlist: only meaningful if the URI parsed cleanly. */ |
93 | 1.73k | if ((mode & 0x04) && split_ok == 0) { |
94 | 645 | coap_optlist_t *chain = NULL; |
95 | 645 | coap_uri_into_optlist(&parsed_uri, NULL, &chain, mode & 0x08 ? 1 : 0); |
96 | 645 | coap_delete_optlist(chain); |
97 | 645 | } |
98 | | |
99 | 1.73k | coap_cleanup(); |
100 | 1.73k | return 0; |
101 | 1.75k | } |