Coverage Report

Created: 2025-10-10 06:06

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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
}