Coverage Report

Created: 2026-05-30 06:12

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/bufferevent_fuzzer.cc
Line
Count
Source
1
/* Copyright 2026 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
608
static void read_cb(struct bufferevent *bev, void *ctx) {
29
608
    struct evbuffer *input = bufferevent_get_input(bev);
30
608
    evbuffer_drain(input, evbuffer_get_length(input));
31
608
}
32
33
0
static void event_cb(struct bufferevent *bev, short what, void *ctx) {
34
0
}
35
36
676
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
37
676
  if (size < 16) return 0;
38
39
670
  FuzzedDataProvider data_provider(data, size);
40
41
670
  std::string s1 = data_provider.ConsumeRandomLengthString();
42
670
  std::string s2 = data_provider.ConsumeRandomLengthString();
43
670
  uint32_t val1 = data_provider.ConsumeIntegral<uint32_t>();
44
670
  uint32_t val2 = data_provider.ConsumeIntegral<uint32_t>();
45
670
  uint32_t val3 = data_provider.ConsumeIntegral<uint32_t>();
46
670
  uint32_t val4 = data_provider.ConsumeIntegral<uint32_t>();
47
48
670
  int use_pair = val1 % 2;
49
670
  int read_write = val2 % 2;
50
670
  int use_filter = val4 % 2;
51
52
670
  int options1 = val2 % 16;
53
670
  int options2 = val3 % 16;
54
55
670
  struct bufferevent *bev1 = NULL, *bev2 = NULL, *bev3 = NULL, *bev4 = NULL,
56
670
                     *pair[2];
57
670
  struct event_base *base = NULL;
58
670
  struct evbuffer *evbuf = NULL;
59
670
  struct ev_token_bucket_cfg *conn_bucket_cfg = NULL;
60
670
  struct bufferevent_rate_limit_group *bev_rate_group = NULL;
61
670
  char buf[128];
62
63
  /*create a buffer event*/
64
670
  struct event_config *cfg = event_config_new();
65
670
  if (val1 % 3 == 1) {
66
103
    event_config_avoid_method(cfg, "epoll");
67
567
  } else if (val1 % 3 == 2) {
68
150
    event_config_avoid_method(cfg, "epoll");
69
150
    event_config_avoid_method(cfg, "poll");
70
150
  }
71
670
  base = event_base_new_with_config(cfg);
72
670
  event_config_free(cfg);
73
670
  if (!base) return 0;
74
75
670
  if (use_pair == 0) {
76
567
    if (bufferevent_pair_new(base, options1, pair) == -1) {
77
14
      event_base_free(base);
78
14
      return 0;
79
14
    }
80
553
    bev1 = pair[0];
81
553
    bev2 = pair[1];
82
553
  } else {
83
103
    bev1 = bufferevent_socket_new(base, -1, options1);
84
103
    bev2 = bufferevent_socket_new(base, -1, options2);
85
103
  }
86
87
  /*bufferevent_filter_new*/
88
656
  if (use_filter == 0 && bev1 && bev2) {
89
    /*we cannot use BEV_OPT_CLOSE_ON_FREE when freeing bufferevents*/
90
476
    bev3 = bufferevent_filter_new(
91
476
        bev1, NULL, NULL, options1 & (~BEV_OPT_CLOSE_ON_FREE), NULL, NULL);
92
476
    bev4 = bufferevent_filter_new(
93
476
        bev2, NULL, NULL, options2 & (~BEV_OPT_CLOSE_ON_FREE), NULL, NULL);
94
95
476
    if (bev3) {
96
      // bev1 is now "under" bev3
97
469
    } else {
98
7
      bufferevent_free(bev1);
99
7
      bev1 = NULL;
100
7
    }
101
476
    if (bev4) {
102
      // bev2 is now "under" bev4
103
468
    } else {
104
8
      bufferevent_free(bev2);
105
8
      bev2 = NULL;
106
8
    }
107
476
  } else {
108
180
    bev3 = bev1;
109
180
    bev4 = bev2;
110
180
  }
111
112
656
  if (!bev3 || !bev4) {
113
32
    goto cleanup;
114
32
  }
115
116
624
  if (bufferevent_priority_set(bev3, val2 % 8) == 0) {
117
6
    bufferevent_get_priority(bev3);
118
6
  }
119
120
  /*set rate limits*/
121
624
  bufferevent_set_rate_limit(bev3, NULL);
122
624
  struct timeval cfg_tick;
123
624
  cfg_tick.tv_sec = val1 % 10;
124
624
  cfg_tick.tv_usec = val2 % 1000000;
125
624
  conn_bucket_cfg = ev_token_bucket_cfg_new(val1 % 1024 + 1, val2 % 2048 + 1, 
126
624
                                           val3 % 1024 + 1, val4 % 2048 + 1, &cfg_tick);
127
624
  if (conn_bucket_cfg) {
128
279
    bev_rate_group = bufferevent_rate_limit_group_new(base, conn_bucket_cfg);
129
279
    if (bev_rate_group) {
130
279
        bufferevent_add_to_rate_limit_group(bev4, bev_rate_group);
131
279
    }
132
279
  }
133
134
  /*write and read from buffer events*/
135
624
  bufferevent_setcb(bev3, read_cb, NULL, event_cb, NULL);
136
624
  bufferevent_setcb(bev4, read_cb, NULL, event_cb, NULL);
137
624
  bufferevent_enable(bev3, EV_READ | EV_WRITE);
138
624
  bufferevent_enable(bev4, EV_READ | EV_WRITE);
139
140
624
  bufferevent_write(bev3, s1.c_str(), s1.size());
141
624
  bufferevent_write(bev4, s2.c_str(), s2.size());
142
  
143
  /* Run loop briefly */
144
624
  event_base_loop(base, EVLOOP_NONBLOCK);
145
146
624
  bufferevent_write_buffer(bev3, bufferevent_get_input(bev4));
147
148
624
  evbuf = evbuffer_new();
149
624
  if (evbuf) {
150
624
    bufferevent_read_buffer(bev3, evbuf);
151
624
    evbuffer_free(evbuf);
152
624
  }
153
624
  bufferevent_read(bev3, buf, sizeof(buf));
154
155
624
  if (bev_rate_group) {
156
279
    bufferevent_remove_from_rate_limit_group(bev4);
157
279
  }
158
159
  /*watermarks*/
160
624
  if (read_write == 0) {
161
550
    bufferevent_setwatermark(bev4, EV_READ, val1 % 1024, val2 % 2048);
162
550
  } else {
163
74
    bufferevent_setwatermark(bev4, EV_WRITE, val1 % 1024, val2 % 2048);
164
74
  }
165
166
  /*clean up*/
167
656
cleanup:
168
656
  if (bev3) bufferevent_free(bev3);
169
656
  if (bev4) bufferevent_free(bev4);
170
656
  if (conn_bucket_cfg) ev_token_bucket_cfg_free(conn_bucket_cfg);
171
656
  if (bev_rate_group) bufferevent_rate_limit_group_free(bev_rate_group);
172
656
  if (base) event_base_free(base);
173
174
656
  return 0;
175
624
}