Coverage Report

Created: 2025-07-11 06:21

/src/bufferevent_fuzzer.cc
Line
Count
Source (jump to first uncovered line)
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
311
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
29
30
311
  FuzzedDataProvider data_provider(data, size);
31
32
311
  std::string s1 = data_provider.ConsumeRandomLengthString();
33
311
  std::string s2 = data_provider.ConsumeRandomLengthString();
34
311
  size_t int1 = data_provider.ConsumeIntegral<size_t>();
35
311
  size_t int2 = data_provider.ConsumeIntegral<size_t>();
36
311
  size_t int3 = data_provider.ConsumeIntegral<size_t>();
37
311
  size_t int4 = data_provider.ConsumeIntegral<size_t>();
38
39
311
  int use_pair = int1 % 2;
40
311
  int read_write = int2 % 2;
41
311
  int use_filter = int4 % 2;
42
43
311
  int options1 = int2 % 16;
44
311
  int options2 = int3 % 16;
45
46
311
  struct bufferevent *bev1 = NULL, *bev2 = NULL, *bev3 = NULL, *bev4 = NULL,
47
311
                     *pair[2];
48
311
  struct event_base *base = NULL;
49
311
  struct evbuffer *evbuf = NULL;
50
311
  static struct ev_token_bucket_cfg *conn_bucket_cfg = NULL;
51
311
  struct bufferevent_rate_limit_group *bev_rate_group = NULL;
52
311
  char buf[128];
53
54
  /*create a buffer event*/
55
311
  base = event_base_new();
56
311
  if (use_pair == 0) {
57
239
    if (bufferevent_pair_new(base, options1, pair) == -1) {
58
18
      event_base_free(base);
59
18
      return 0;
60
18
    }
61
221
    bev1 = pair[0];
62
221
    bev2 = pair[1];
63
221
    assert(bufferevent_pair_get_partner(bev1) != NULL);
64
221
  } else {
65
72
    bev1 = bufferevent_socket_new(base, -1, options1);
66
72
    bev2 = bufferevent_socket_new(base, -1, options2);
67
72
  }
68
69
  /*bufferevent_filter_new*/
70
293
  if (use_filter == 0) {
71
72
    /*we cannot use BEV_OPT_CLOSE_ON_FREE when freeing bufferevents*/
73
252
    bev3 = bufferevent_filter_new(
74
252
        bev1, NULL, NULL, options1 & (~BEV_OPT_CLOSE_ON_FREE), NULL, NULL);
75
252
    bev4 = bufferevent_filter_new(
76
252
        bev2, NULL, NULL, options2 & (~BEV_OPT_CLOSE_ON_FREE), NULL, NULL);
77
78
252
    if (bev1) {
79
235
      bufferevent_free(bev1);
80
235
    }
81
252
    if (bev2) {
82
236
      bufferevent_free(bev2);
83
236
    }
84
252
  } else {
85
41
    bev3 = bev1;
86
41
    bev4 = bev2;
87
41
  }
88
89
293
  if (!bev3 || !bev4) {
90
45
    goto cleanup;
91
45
  }
92
93
248
  if (bufferevent_priority_set(bev3, options2) == 0) {
94
5
    assert(bufferevent_get_priority(bev3) == options2);
95
5
  }
96
97
  /*set rate limits*/
98
248
  assert(bufferevent_set_rate_limit(bev3, NULL) != -1);
99
248
  static struct timeval cfg_tick = {static_cast<__time_t>(int1),
100
248
                                    static_cast<__suseconds_t>(int2)};
101
248
  conn_bucket_cfg = ev_token_bucket_cfg_new(int1, int2, int3, int4, &cfg_tick);
102
248
  if (!conn_bucket_cfg) {
103
248
    goto cleanup;
104
248
  }
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
293
cleanup:
136
293
  if (bev3) {
137
260
    bufferevent_free(bev3);
138
260
  }
139
293
  if (bev4) {
140
263
    bufferevent_free(bev4);
141
263
  }
142
293
  if (conn_bucket_cfg) {
143
0
    ev_token_bucket_cfg_free(conn_bucket_cfg);
144
0
    conn_bucket_cfg = NULL;
145
0
  }
146
147
293
  if (bev_rate_group) {
148
0
    bufferevent_rate_limit_group_free(bev_rate_group);
149
0
  }
150
151
293
  event_base_free(base);
152
153
293
  return 0;
154
0
}