Coverage Report

Created: 2025-08-29 06:35

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