From 80c6562e597080fab85b304d23d7e31a5f7604f4 Mon Sep 17 00:00:00 2001 From: Miklos Vajna Date: Thu, 22 Apr 2021 11:58:28 +0200 Subject: [PATCH] Add a fuzzer for http::StatusLine::parse() And fix an unhandled std::length_error it found. Signed-off-by: Miklos Vajna Change-Id: I571cdd71caeda84820f2c64088966936637ce2bf --- Makefile.am | 13 ++++++++++++- fuzzer/HttpStatus.cpp | 15 +++++++++++++++ fuzzer/README | 12 ++++++++++++ ...crash-157ccefc8caa188faa51f4348d338557ef78d0d1 | 2 ++ fuzzer/httpstatus-data/load | 1 + net/HttpRequest.cpp | 8 +++++++- 6 files changed, 49 insertions(+), 2 deletions(-) create mode 100644 fuzzer/HttpStatus.cpp create mode 100644 fuzzer/httpstatus-data/crash-157ccefc8caa188faa51f4348d338557ef78d0d1 create mode 100644 fuzzer/httpstatus-data/load diff --git a/Makefile.am b/Makefile.am index 723815d6f1..0df79b12eb 100644 --- a/Makefile.am +++ b/Makefile.am @@ -145,7 +145,8 @@ if ENABLE_LIBFUZZER noinst_PROGRAMS += \ admin_fuzzer \ clientsession_fuzzer \ - httpheader_fuzzer + httpheader_fuzzer \ + httpstatus_fuzzer else noinst_PROGRAMS += loolwsd_fuzzer endif @@ -206,6 +207,16 @@ httpheader_fuzzer_SOURCES = \ fuzzer/HttpHeader.cpp httpheader_fuzzer_LDFLAGS = -fsanitize=fuzzer $(AM_LDFLAGS) +httpstatus_fuzzer_CPPFLAGS = \ + -DKIT_IN_PROCESS=1 \ + $(AM_CPPFLAGS) +httpstatus_fuzzer_SOURCES = \ + $(loolwsd_sources) \ + $(loolforkit_sources) \ + $(shared_sources) \ + fuzzer/HttpStatus.cpp +httpstatus_fuzzer_LDFLAGS = -fsanitize=fuzzer $(AM_LDFLAGS) + clientnb_SOURCES = net/clientnb.cpp \ common/Log.cpp \ common/StringVector.cpp \ diff --git a/fuzzer/HttpStatus.cpp b/fuzzer/HttpStatus.cpp new file mode 100644 index 0000000000..8fb9163dd8 --- /dev/null +++ b/fuzzer/HttpStatus.cpp @@ -0,0 +1,15 @@ +#include + +#include "config.h" + +#include + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) +{ + http::StatusLine statusLine; + int64_t length = size; + statusLine.parse(reinterpret_cast(data), length); + return 0; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/fuzzer/README b/fuzzer/README index de16da5cba..ed556cf921 100644 --- a/fuzzer/README +++ b/fuzzer/README @@ -18,3 +18,15 @@ Run the fuzzers like this: ---- ./clientsession_fuzzer -max_len=16384 fuzzer/data/ ---- + +- HttpHeader (less useful, found no problems so far): + +---- +./httpheader_fuzzer -max_len=16384 fuzzer/httpheader-data/ +---- + +- HttpStatus: + +---- +./httpstatus_fuzzer -max_len=16384 fuzzer/httpstatus-data/ +---- diff --git a/fuzzer/httpstatus-data/crash-157ccefc8caa188faa51f4348d338557ef78d0d1 b/fuzzer/httpstatus-data/crash-157ccefc8caa188faa51f4348d338557ef78d0d1 new file mode 100644 index 0000000000..7849a8a21e --- /dev/null +++ b/fuzzer/httpstatus-data/crash-157ccefc8caa188faa51f4348d338557ef78d0d1 @@ -0,0 +1,2 @@ +HTTP/1.1 101 +t diff --git a/fuzzer/httpstatus-data/load b/fuzzer/httpstatus-data/load new file mode 100644 index 0000000000..1fb1e197fb --- /dev/null +++ b/fuzzer/httpstatus-data/load @@ -0,0 +1 @@ +HTTP/1.1 101 Something Something diff --git a/net/HttpRequest.cpp b/net/HttpRequest.cpp index dec5ab808d..6ee7fb88e9 100644 --- a/net/HttpRequest.cpp +++ b/net/HttpRequest.cpp @@ -259,7 +259,13 @@ FieldParseState StatusLine::parse(const char* p, int64_t& len) } } - _reasonPhrase = std::string(&p[reasonOff], off - reasonOff - 1); // Exclude '\r'. + int64_t stringSize = off - reasonOff - 1; // Exclude '\r'. + if (stringSize < 0) + { + LOG_ERR("StatusLine::parse: missing line break"); + return FieldParseState::Invalid; + } + _reasonPhrase = std::string(&p[reasonOff], stringSize); // Consume the line breaks. for (; off < len; ++off)