Coverage Report

Created: 2025-10-10 06:41

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/bufferevent_fuzzer.cc
Line
Count
Source
1
/* Copyright 2023 Google LLC
2
Licensed under the Apache License, Version 2.0 (the "License");
3
you may not use this file except in compliance with the License.
4
You may obtain a copy of the License at
5
      http://www.apache.org/licenses/LICENSE-2.0
6
Unless required by applicable law or agreed to in writing, software
7
distributed under the License is distributed on an "AS IS" BASIS,
8
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
9
See the License for the specific language governing permissions and
10
limitations under the License.
11
*/
12
13
#include <assert.h>
14
#include <stddef.h>
15
#include <stdint.h>
16
#include <stdlib.h>
17
#include <string>
18
#include <sys/socket.h>
19
20
#include <fuzzer/FuzzedDataProvider.h>
21
22
extern "C" {
23
#include "libevent/include/event2/buffer.h"
24
#include "libevent/include/event2/bufferevent.h"
25
#include "libevent/include/event2/event.h"
26
}
27
28
370
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
29
30
370
  FuzzedDataProvider data_provider(data, size);
31
32
370
  std::string s1 = data_provider.ConsumeRandomLengthString();
33
370
  std::string s2 = data_provider.ConsumeRandomLengthString();
34
370
  size_t int1 = data_provider.ConsumeIntegral<size_t>();
35
370
  size_t int2 = data_provider.ConsumeIntegral<size_t>();
36
370
  size_t int3 = data_provider.ConsumeIntegral<size_t>();
37
370
  size_t int4 = data_provider.ConsumeIntegral<size_t>();
38
39
370
  int use_pair = int1 % 2;
40
370
  int read_write = int2 % 2;
41
370
  int use_filter = int4 % 2;
42
43
370
  int options1 = int2 % 16;
44
370
  int options2 = int3 % 16;
45
46
370
  struct bufferevent *bev1 = NULL, *bev2 = NULL, *bev3 = NULL, *bev4 = NULL,
47
370
                     *pair[2];
48
370
  struct event_base *base = NULL;
49
370
  struct evbuffer *evbuf = NULL;
50
370
  static struct ev_token_bucket_cfg *conn_bucket_cfg = NULL;
51
370
  struct bufferevent_rate_limit_group *bev_rate_group = NULL;
52
370
  char buf[128];
53
54
  /*create a buffer event*/
55
370
  base = event_base_new();
56
370
  if (use_pair == 0) {
57
285
    if (bufferevent_pair_new(base, options1, pair) == -1) {
58
19
      event_base_free(base);
59
19
      return 0;
60
19
    }
61
266
    bev1 = pair[0];
62
266
    bev2 = pair[1];
63
266
    assert(bufferevent_pair_get_partner(bev1) != NULL);
64
266
  } else {
65
85
    bev1 = bufferevent_socket_new(base, -1, options1);
66
85
    bev2 = bufferevent_socket_new(base, -1, options2);
67
85
  }
68
69
  /*bufferevent_filter_new*/
70
351
  if (use_filter == 0) {
71
72
    /*we cannot use BEV_OPT_CLOSE_ON_FREE when freeing bufferevents*/
73
314
    bev3 = bufferevent_filter_new(
74
314
        bev1, NULL, NULL, options1 & (~BEV_OPT_CLOSE_ON_FREE), NULL, NULL);
75
314
    bev4 = bufferevent_filter_new(
76
314
        bev2, NULL, NULL, options2 & (~BEV_OPT_CLOSE_ON_FREE), NULL, NULL);
77
78
314
    if (bev1) {
79
295
      bufferevent_free(bev1);
80
295
    }
81
314
    if (bev2) {
82
293
      bufferevent_free(bev2);
83
293
    }
84
314
  } else {
85
37
    bev3 = bev1;
86
37
    bev4 = bev2;
87
37
  }
88
89
351
  if (!bev3 || !bev4) {
90
66
    goto cleanup;
91
66
  }
92
93
285
  if (bufferevent_priority_set(bev3, options2) == 0) {
94
5
    assert(bufferevent_get_priority(bev3) == options2);
95
5
  }
96
97
  /*set rate limits*/
98
285
  assert(bufferevent_set_rate_limit(bev3, NULL) != -1);
99
285
  static struct timeval cfg_tick = {static_cast<__time_t>(int1),
100
285
                                    static_cast<__suseconds_t>(int2)};
101
285
  conn_bucket_cfg = ev_token_bucket_cfg_new(int1, int2, int3, int4, &cfg_tick);
102
285
  if (!conn_bucket_cfg) {
103
285
    goto cleanup;
104
285
  }
105
106
0
  bev_rate_group = bufferevent_rate_limit_group_new(base, conn_bucket_cfg);
107
0
  assert(bufferevent_add_to_rate_limit_group(bev4, bev_rate_group) != -1);
108
109
  /*write and read from buffer events*/
110
0
  bufferevent_write(bev3, s1.c_str(), s1.size());
111
0
  bufferevent_write(bev4, s2.c_str(), s2.size());
112
0
  bufferevent_write_buffer(bev3, bufferevent_get_input(bev4));
113
114
0
  evbuf = evbuffer_new();
115
0
  bufferevent_read_buffer(bev3, evbuf);
116
0
  evbuffer_free(evbuf);
117
0
  bufferevent_read(bev3, buf, sizeof(buf) - 1);
118
0
  bufferevent_remove_from_rate_limit_group(bev4);
119
120
  /*watermarks*/
121
0
  if (read_write == 0) {
122
0
    bufferevent_setwatermark(bev4, EV_READ, int1, int2);
123
0
    bufferevent_getwatermark(bev4, EV_READ, &int3, NULL);
124
0
    bufferevent_getwatermark(bev4, EV_READ, NULL, &int4);
125
0
  } else {
126
0
    bufferevent_setwatermark(bev4, EV_WRITE, int1, int2);
127
0
    bufferevent_getwatermark(bev4, EV_WRITE, &int3, NULL);
128
0
    bufferevent_getwatermark(bev4, EV_WRITE, NULL, &int4);
129
0
  }
130
131
0
  assert(int1 == int3);
132
0
  assert(int2 == int4);
133
134
  /*clean up*/
135
351
cleanup:
136
351
  if (bev3) {
137
318
    bufferevent_free(bev3);
138
318
  }
139
351
  if (bev4) {
140
307
    bufferevent_free(bev4);
141
307
  }
142
351
  if (conn_bucket_cfg) {
143
0
    ev_token_bucket_cfg_free(conn_bucket_cfg);
144
0
    conn_bucket_cfg = NULL;
145
0
  }
146
147
351
  if (bev_rate_group) {
148
0
    bufferevent_rate_limit_group_free(bev_rate_group);
149
0
  }
150
151
351
  event_base_free(base);
152
153
351
  return 0;
154
0
}