OSS-Fuzz: Add new fuzzer/options targets websocket (#2663)

Add websocket_fuzzer covering frame reading, UTF-8 and close payload validation, and the upgrade response parser. Add websocket_fuzzer.options to raise max_len above the 64 KiB frame length boundary.
This commit is contained in:
Arthur Chan authored and GitHub committed 2026-11-12 20:47:22 -05:00
1 parent a39e081386
commit a2ebab183d
3 files changed
+60 -1

No files matched your search

+4 -1
View File
@@ -13,7 +13,7 @@ ZLIB_SUPPORT = -DCPPHTTPLIB_ZLIB_SUPPORT -lz
BROTLI_DIR = /usr/local/opt/brotli BROTLI_DIR = /usr/local/opt/brotli
# BROTLI_SUPPORT = -DCPPHTTPLIB_BROTLI_SUPPORT -I$(BROTLI_DIR)/include -L$(BROTLI_DIR)/lib -lbrotlicommon -lbrotlienc -lbrotlidec # BROTLI_SUPPORT = -DCPPHTTPLIB_BROTLI_SUPPORT -I$(BROTLI_DIR)/include -L$(BROTLI_DIR)/lib -lbrotlicommon -lbrotlienc -lbrotlidec
FUZZERS = server_fuzzer url_parser_fuzzer header_parser_fuzzer client_fuzzer multipart_parser_fuzzer FUZZERS = server_fuzzer url_parser_fuzzer header_parser_fuzzer client_fuzzer multipart_parser_fuzzer websocket_fuzzer
# Runs all the tests and also fuzz tests against seed corpus. # Runs all the tests and also fuzz tests against seed corpus.
all : $(FUZZERS) all : $(FUZZERS)
@@ -38,5 +38,8 @@ url_parser_fuzzer : url_parser_fuzzer.cc ../../httplib.h
multipart_parser_fuzzer : multipart_parser_fuzzer.cc ../../httplib.h multipart_parser_fuzzer : multipart_parser_fuzzer.cc ../../httplib.h
$(CXX) $(CXXFLAGS) -o $@ $< $(ZLIB_SUPPORT) $(LIB_FUZZING_ENGINE) -pthread -lanl $(CXX) $(CXXFLAGS) -o $@ $< $(ZLIB_SUPPORT) $(LIB_FUZZING_ENGINE) -pthread -lanl
websocket_fuzzer : websocket_fuzzer.cc ../../httplib.h
$(CXX) $(CXXFLAGS) -o $@ $< $(ZLIB_SUPPORT) $(LIB_FUZZING_ENGINE) -pthread -lanl
clean: clean:
rm -f server_fuzzer pem *.0 *.o *.1 *.srl *.zip rm -f server_fuzzer pem *.0 *.o *.1 *.srl *.zip
+54
View File
@@ -0,0 +1,54 @@
#include <cstdint>
#include <string>
#include <httplib.h>
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
if (size < 2) { return 0; }
auto selector = data[0];
std::string input(reinterpret_cast<const char *>(data + 1), size - 1);
switch (selector % 4) {
case 0: {
// read_websocket_frame. WebSocket::read passes the macro, close() passes
// 125, and 0 means no limit
static const size_t max_lens[] = {0, 125,
CPPHTTPLIB_WEBSOCKET_MAX_PAYLOAD_LENGTH};
auto expect_masked = (selector / 4) % 2 != 0;
auto max_len = max_lens[(selector / 8) % 3];
httplib::detail::BufferStream strm;
strm.write(input.data(), input.size());
auto opcode = httplib::ws::Opcode::Text;
std::string payload;
auto fin = false;
httplib::ws::impl::read_websocket_frame(strm, opcode, payload, fin,
expect_masked, max_len);
break;
}
case 1: {
// is_valid_utf8
httplib::ws::impl::is_valid_utf8(input);
break;
}
case 2: {
// is_valid_close_payload
httplib::ws::impl::is_valid_close_payload(input);
break;
}
case 3: {
// read_websocket_upgrade_response, with a fixed key since
// perform_websocket_handshake draws a random one
static const auto expected_accept =
httplib::detail::websocket_accept_key("dGhlIHNhbXBsZSBub25jZQ==");
httplib::detail::BufferStream strm;
strm.write(input.data(), input.size());
httplib::detail::WebSocketUpgradeResponse upgrade;
httplib::detail::read_websocket_upgrade_response(strm, expected_accept,
"chat, stream", upgrade);
break;
}
}
return 0;
}
+2
View File
@@ -0,0 +1,2 @@
[libfuzzer]
max_len = 70000