From 95d0b073bd3ae1300aad65d1ab95a43bcbeb30f0 Mon Sep 17 00:00:00 2001 From: yhirose Date: Sat, 14 Nov 2020 21:25:07 -0500 Subject: [PATCH] Fix #754 --- httplib.h | 38 ++++++++++++++++++++++++++++++++++- test/fuzzing/server_fuzzer.cc | 2 ++ 2 files changed, 39 insertions(+), 1 deletion(-) diff --git a/httplib.h b/httplib.h index 1c0fa5c..c17f340 100644 --- a/httplib.h +++ b/httplib.h @@ -480,6 +480,7 @@ public: virtual ssize_t read(char *ptr, size_t size) = 0; virtual ssize_t write(const char *ptr, size_t size) = 0; virtual void get_remote_ip_and_port(std::string &ip, int &port) const = 0; + virtual socket_t socket() const = 0; template ssize_t write_format(const char *fmt, const Args &... args); @@ -1627,6 +1628,10 @@ inline ssize_t select_read(socket_t sock, time_t sec, time_t usec) { return handle_EINTR([&]() { return poll(&pfd_read, 1, timeout); }); #else +#ifndef _WIN32 + if (sock >= FD_SETSIZE) { return 1; } +#endif + fd_set fds; FD_ZERO(&fds); FD_SET(sock, &fds); @@ -1651,6 +1656,10 @@ inline ssize_t select_write(socket_t sock, time_t sec, time_t usec) { return handle_EINTR([&]() { return poll(&pfd_read, 1, timeout); }); #else +#ifndef _WIN32 + if (sock >= FD_SETSIZE) { return 1; } +#endif + fd_set fds; FD_ZERO(&fds); FD_SET(sock, &fds); @@ -1684,6 +1693,10 @@ inline bool wait_until_socket_is_ready(socket_t sock, time_t sec, time_t usec) { } return false; #else +#ifndef _WIN32 + if (sock >= FD_SETSIZE) { return false; } +#endif + fd_set fdsr; FD_ZERO(&fdsr); FD_SET(sock, &fdsr); @@ -1721,6 +1734,7 @@ public: ssize_t read(char *ptr, size_t size) override; ssize_t write(const char *ptr, size_t size) override; void get_remote_ip_and_port(std::string &ip, int &port) const override; + socket_t socket() const override; private: socket_t sock_; @@ -1743,6 +1757,7 @@ public: ssize_t read(char *ptr, size_t size) override; ssize_t write(const char *ptr, size_t size) override; void get_remote_ip_and_port(std::string &ip, int &port) const override; + socket_t socket() const override; private: socket_t sock_; @@ -1764,6 +1779,7 @@ public: ssize_t read(char *ptr, size_t size) override; ssize_t write(const char *ptr, size_t size) override; void get_remote_ip_and_port(std::string &ip, int &port) const override; + socket_t socket() const override; const std::string &get_buffer() const; @@ -2980,7 +2996,7 @@ public: bool is_valid() const { return is_valid_; } bool parse(const char *buf, size_t n, const ContentReceiver &content_callback, - const MultipartContentHeader &header_callback) { + const MultipartContentHeader &header_callback) { static const std::regex re_content_disposition( "^Content-Disposition:\\s*form-data;\\s*name=\"(.*?)\"(?:;\\s*filename=" @@ -3792,6 +3808,8 @@ inline void SocketStream::get_remote_ip_and_port(std::string &ip, return detail::get_remote_ip_and_port(sock_, ip, port); } +inline socket_t SocketStream::socket() const { return sock_; } + // Buffer stream implementation inline bool BufferStream::is_readable() const { return true; } @@ -3815,6 +3833,8 @@ inline ssize_t BufferStream::write(const char *ptr, size_t size) { inline void BufferStream::get_remote_ip_and_port(std::string & /*ip*/, int & /*port*/) const {} +inline socket_t BufferStream::socket() const { return 0; } + inline const std::string &BufferStream::get_buffer() const { return buffer; } } // namespace detail @@ -4614,6 +4634,20 @@ Server::process_request(Stream &strm, bool close_connection, res.version = "HTTP/1.1"; +#ifdef _WIN32 + // TODO: Increase FD_SETSIZE statically (libzmq), dynamically (MySQL). +#else +#ifndef CPPHTTPLIB_USE_POLL + // Socket file descriptor exceeded FD_SETSIZE... + if (strm.socket() >= FD_SETSIZE) { + Headers dummy; + detail::read_headers(strm, dummy); + res.status = 500; + return write_response(strm, close_connection, req, res); + } +#endif +#endif + // Check if the request URI doesn't exceed the limit if (line_reader.size() > CPPHTTPLIB_REQUEST_URI_MAX_LENGTH) { Headers dummy; @@ -5864,6 +5898,8 @@ inline void SSLSocketStream::get_remote_ip_and_port(std::string &ip, detail::get_remote_ip_and_port(sock_, ip, port); } +inline socket_t SSLSocketStream::socket() const { return sock_; } + static SSLInit sslinit_; } // namespace detail diff --git a/test/fuzzing/server_fuzzer.cc b/test/fuzzing/server_fuzzer.cc index 420ae69..5ea1032 100644 --- a/test/fuzzing/server_fuzzer.cc +++ b/test/fuzzing/server_fuzzer.cc @@ -35,6 +35,8 @@ class FuzzedStream : public httplib::Stream { port = 8080; } + socket_t socket() const override { return 0; } + private: const uint8_t* data_; size_t size_;