Coverage Report

Created: 2026-05-11 06:49

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