Coverage Report

Created: 2026-09-01 06:26

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/cpp-httplib/test/fuzzing/client_fuzzer.cc
Line
Count
Source
1
#include <cstdint>
2
#include <cstring>
3
#include <httplib.h>
4
5
class FuzzedStream : public httplib::Stream {
6
public:
7
  FuzzedStream(const uint8_t *data, size_t size)
8
9.56k
      : data_(data), size_(size), read_pos_(0) {}
9
10
17.5M
  ssize_t read(char *ptr, size_t size) override {
11
17.5M
    if (size + read_pos_ > size_) { size = size_ - read_pos_; }
12
17.5M
    memcpy(ptr, data_ + read_pos_, size);
13
17.5M
    read_pos_ += size;
14
17.5M
    return static_cast<ssize_t>(size);
15
17.5M
  }
16
17
9.56k
  ssize_t write(const char *ptr, size_t size) override {
18
9.56k
    request_.append(ptr, size);
19
9.56k
    return static_cast<ssize_t>(size);
20
9.56k
  }
21
22
0
  ssize_t write(const char *ptr) { return write(ptr, strlen(ptr)); }
23
24
0
  ssize_t write(const std::string &s) { return write(s.data(), s.size()); }
25
26
1.41k
  bool is_readable() const override { return true; }
27
28
0
  bool wait_readable() const override { return true; }
29
30
0
  bool wait_writable() const override { return true; }
31
32
0
  void get_remote_ip_and_port(std::string &ip, int &port) const override {
33
0
    ip = "127.0.0.1";
34
0
    port = 8080;
35
0
  }
36
37
0
  void get_local_ip_and_port(std::string &ip, int &port) const override {
38
0
    ip = "127.0.0.1";
39
0
    port = 8080;
40
0
  }
41
42
4.49k
  socket_t socket() const override { return 0; }
43
44
0
  time_t duration() const override { return 0; };
45
46
private:
47
  const uint8_t *data_;
48
  size_t size_;
49
  size_t read_pos_;
50
  std::string request_;
51
};
52
53
class FuzzableClient : public httplib::ClientImpl {
54
public:
55
3.10k
  FuzzableClient() : httplib::ClientImpl("localhost", 8080) {}
56
57
3.10k
  void ProcessFuzzedResponse(FuzzedStream &stream, const std::string &method) {
58
3.10k
    httplib::Request req;
59
3.10k
    req.method = method;
60
3.10k
    req.path = "/";
61
3.10k
    httplib::Response res;
62
3.10k
    bool close_connection = false;
63
3.10k
    httplib::Error error = httplib::Error::Success;
64
65
3.10k
    process_request(stream, req, res, close_connection, error);
66
3.10k
  }
67
};
68
69
4.65k
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
70
4.65k
  if (size < 1) return 0;
71
72
4.65k
  FuzzedStream stream{data + 1, size - 1};
73
4.65k
  FuzzableClient client;
74
75
  // Use the first byte to select method
76
4.65k
  std::string method;
77
4.65k
  switch (data[0] % 6) {
78
770
  case 0: method = "GET"; break;
79
724
  case 1: method = "POST"; break;
80
1.08k
  case 2: method = "PUT"; break;
81
449
  case 3: method = "PATCH"; break;
82
591
  case 4: method = "DELETE"; break;
83
1.04k
  case 5: method = "OPTIONS"; break;
84
4.65k
  }
85
86
4.65k
  client.ProcessFuzzedResponse(stream, method);
87
4.65k
  return 0;
88
4.65k
}