client_fuzzer.cc 2.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  1. #include <cstdint>
  2. #include <cstring>
  3. #include <httplib.h>
  4. class FuzzedStream : public httplib::Stream {
  5. public:
  6. FuzzedStream(const uint8_t *data, size_t size)
  7. : data_(data), size_(size), read_pos_(0) {}
  8. ssize_t read(char *ptr, size_t size) override {
  9. if (size + read_pos_ > size_) { size = size_ - read_pos_; }
  10. memcpy(ptr, data_ + read_pos_, size);
  11. read_pos_ += size;
  12. return static_cast<ssize_t>(size);
  13. }
  14. ssize_t write(const char *ptr, size_t size) override {
  15. request_.append(ptr, size);
  16. return static_cast<ssize_t>(size);
  17. }
  18. ssize_t write(const char *ptr) { return write(ptr, strlen(ptr)); }
  19. ssize_t write(const std::string &s) { return write(s.data(), s.size()); }
  20. bool is_readable() const override { return true; }
  21. bool wait_readable() const override { return true; }
  22. bool wait_writable() const override { return true; }
  23. void get_remote_ip_and_port(std::string &ip, int &port) const override {
  24. ip = "127.0.0.1";
  25. port = 8080;
  26. }
  27. void get_local_ip_and_port(std::string &ip, int &port) const override {
  28. ip = "127.0.0.1";
  29. port = 8080;
  30. }
  31. socket_t socket() const override { return 0; }
  32. time_t duration() const override { return 0; };
  33. private:
  34. const uint8_t *data_;
  35. size_t size_;
  36. size_t read_pos_;
  37. std::string request_;
  38. };
  39. class FuzzableClient : public httplib::ClientImpl {
  40. public:
  41. FuzzableClient() : httplib::ClientImpl("localhost", 8080) {}
  42. void ProcessFuzzedResponse(FuzzedStream &stream, const std::string &method) {
  43. httplib::Request req;
  44. req.method = method;
  45. req.path = "/";
  46. httplib::Response res;
  47. bool close_connection = false;
  48. httplib::Error error = httplib::Error::Success;
  49. process_request(stream, req, res, close_connection, error);
  50. }
  51. };
  52. extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
  53. if (size < 1) return 0;
  54. FuzzedStream stream{data + 1, size - 1};
  55. FuzzableClient client;
  56. // Use the first byte to select method
  57. std::string method;
  58. switch (data[0] % 6) {
  59. case 0: method = "GET"; break;
  60. case 1: method = "POST"; break;
  61. case 2: method = "PUT"; break;
  62. case 3: method = "PATCH"; break;
  63. case 4: method = "DELETE"; break;
  64. case 5: method = "OPTIONS"; break;
  65. }
  66. client.ProcessFuzzedResponse(stream, method);
  67. return 0;
  68. }