/src/fuzz_daemon_connection.cpp
Line | Count | Source |
1 | | // Copyright 2025 Google LLC |
2 | | // |
3 | | // Licensed under the Apache License, Version 2.0 (the "License"); |
4 | | // you may not use this file except in compliance with the License. |
5 | | // You may obtain a copy of the License at |
6 | | // |
7 | | // http://www.apache.org/licenses/LICENSE-2.0 |
8 | | // |
9 | | // Unless required by applicable law or agreed to in writing, software |
10 | | // distributed under the License is distributed on an "AS IS" BASIS, |
11 | | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
12 | | // See the License for the specific language governing permissions and |
13 | | // limitations under the License. |
14 | | // |
15 | | //////////////////////////////////////////////////////////////////////////////// |
16 | | #include <stdint.h> |
17 | | #include <stddef.h> |
18 | | #include <string> |
19 | | #include <vector> |
20 | | #include <cstring> |
21 | | |
22 | | #include "fuzzer/FuzzedDataProvider.h" |
23 | | #include "connection_helper.h" |
24 | | |
25 | | extern "C" { |
26 | | #include "conn_tls_check.h" |
27 | | #include "mempool_funcs.h" |
28 | | #include "mhd_send.h" |
29 | | #include "stream_process_request.h" |
30 | | #include "stream_process_states.h" |
31 | | } |
32 | | |
33 | | // Initialising the memory pool |
34 | 2 | extern "C" int LLVMFuzzerInitialize() { |
35 | 2 | g_pool = mhd_pool_create(g_pool_size, MHD_MEMPOOL_ZEROING_ON_RESET); |
36 | 2 | atexit(destroy_global_pool); |
37 | 2 | return 0; |
38 | 2 | } |
39 | | |
40 | 3 | extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { |
41 | 3 | if (size == 0 || g_pool == nullptr) { |
42 | 0 | return 0; |
43 | 0 | } |
44 | | |
45 | 3 | FuzzedDataProvider fdp(data, size); |
46 | | |
47 | | // Reseting the memory pool for each iteartion |
48 | 3 | mhd_pool_destroy(g_pool); |
49 | 3 | g_pool = mhd_pool_create(g_pool_size, MHD_MEMPOOL_ZEROING_ON_RESET); |
50 | | |
51 | | // Initialising the daemon, connection and other MHD components |
52 | 3 | MHD_Daemon daemon; |
53 | 3 | MHD_Connection connection; |
54 | 3 | init_daemon_connection(fdp, daemon, connection); |
55 | 3 | init_parsing_configuration(fdp, connection); |
56 | 3 | init_connection_buffer(fdp, connection); |
57 | 3 | prepare_headers_and_parse(connection, size); |
58 | | |
59 | | // Randomly choose how many targets to fuzz |
60 | 3 | std::vector<int> selectors; |
61 | 9 | for (int i = 0; i < fdp.ConsumeIntegralInRange<int>(1, 8); i++) { |
62 | 6 | selectors.push_back(fdp.ConsumeIntegralInRange<int>(0, 5)); |
63 | 6 | } |
64 | | |
65 | | // Generate random flags |
66 | 3 | bool use_stream_body = fdp.ConsumeBool(); |
67 | 3 | bool is_nodelay = fdp.ConsumeBool(); |
68 | 3 | bool is_cork = fdp.ConsumeBool(); |
69 | | |
70 | | // Use remaining bytes to generate random body for fuzzing |
71 | 3 | std::string body = fdp.ConsumeRemainingBytesAsString(); |
72 | 3 | size_t body_size = body.size(); |
73 | 3 | if (body_size == 0) { |
74 | 0 | return 0; |
75 | 0 | } |
76 | 3 | prepare_body_and_process(connection, body, body_size, use_stream_body); |
77 | | |
78 | 6 | for (int selector : selectors) { |
79 | 6 | switch (selector) { |
80 | 1 | case 0: { |
81 | 1 | mhd_conn_event_loop_state_update(&connection); |
82 | 1 | break; |
83 | 0 | } |
84 | 1 | case 1: { |
85 | 1 | if (connection.rq.app_act.head_act.act == mhd_ACTION_NO_ACTION && |
86 | 0 | connection.daemon && connection.daemon->req_cfg.cb) { |
87 | 0 | mhd_stream_call_app_request_cb(&connection); |
88 | 0 | } |
89 | 1 | break; |
90 | 0 | } |
91 | 1 | case 2: { |
92 | 1 | if (connection.rq.app_act.head_act.act == mhd_ACTION_POST_PARSE && |
93 | 0 | connection.rq.app_act.head_act.data.post_parse.done_cb != nullptr && |
94 | 0 | is_post_parse_ready(connection)) { |
95 | 0 | mhd_stream_process_req_recv_finished(&connection); |
96 | 0 | } |
97 | 1 | break; |
98 | 0 | } |
99 | 0 | case 3: { |
100 | 0 | mhd_conn_tls_check(&connection); |
101 | 0 | break; |
102 | 0 | } |
103 | 3 | case 4: { |
104 | 3 | mhd_connection_set_nodelay_state(&connection, is_nodelay); |
105 | 3 | break; |
106 | 0 | } |
107 | 0 | default: case 5: { |
108 | 0 | mhd_connection_set_cork_state(&connection, is_cork); |
109 | 0 | break; |
110 | 0 | } |
111 | 6 | } |
112 | 6 | } |
113 | | |
114 | 3 | final_cleanup(connection, daemon); |
115 | 3 | return 0; |
116 | 3 | } |