Coverage Report

Created: 2025-11-24 06:15

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