Skip to content

Commit 8a2481a

Browse files
authored
libmicrohttpd2: Add new fuzzing targets (#13849)
This PR adds a new set of fuzzing targets for daemon request processing and allow the daemon randomly choose which request handler to use. --------- Signed-off-by: Arthur Chan <[email protected]>
1 parent e39652c commit 8a2481a

File tree

4 files changed

+82
-14
lines changed

4 files changed

+82
-14
lines changed

projects/libmicrohttpd2/fuzz_daemon.cpp

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,6 @@ static uint16_t g_listen_port = kPort;
2121
static struct MHD_Daemon* g_daemon = nullptr;
2222
static std::once_flag g_start_once;
2323

24-
std::unique_ptr<FuzzedDataProvider> g_fdp;
25-
std::mutex g_fdp_mu;
26-
2724
static void start_daemon_once() {
2825
if (g_daemon) {
2926
return;
@@ -41,7 +38,11 @@ static void start_daemon_once() {
4138
for (int i = 0; i < 8 && !started; ++i) {
4239
const uint16_t try_port = static_cast<uint16_t>(kPort + i);
4340

44-
g_daemon = MHD_daemon_create(&req_cb, NULL);
41+
if (g_fdp->ConsumeBool()) {
42+
g_daemon = MHD_daemon_create(&req_cb, NULL);
43+
} else {
44+
g_daemon = MHD_daemon_create(&req_cb_stream, NULL);
45+
}
4546
if (!g_daemon) {
4647
continue;
4748
}
@@ -72,11 +73,6 @@ static void start_daemon_once() {
7273
}
7374

7475
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
75-
std::call_once(g_start_once, start_daemon_once);
76-
if (!g_daemon) {
77-
return 0;
78-
}
79-
8076
size_t reqs = 0;
8177

8278
// Put FuzzedDataProvider to global
@@ -85,6 +81,12 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
8581
g_fdp = std::make_unique<FuzzedDataProvider>(data, size);
8682
}
8783

84+
// Start daemon
85+
std::call_once(g_start_once, start_daemon_once);
86+
if (!g_daemon) {
87+
return 0;
88+
}
89+
8890
// Generate random number to determine number of random request to be sent
8991
{
9092
std::lock_guard<std::mutex> lk(g_fdp_mu);

projects/libmicrohttpd2/fuzz_response.cpp

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,6 @@
2323

2424
#include "mhd_helper.h"
2525

26-
std::unique_ptr<FuzzedDataProvider> g_fdp;
27-
std::mutex g_fdp_mu;
28-
2926
static void request_ended_cb(void *cls,
3027
const struct MHD_RequestEndedData *data,
3128
void *request_app_context) {

projects/libmicrohttpd2/mhd_helper.cpp

Lines changed: 65 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,8 @@
2626
#include <errno.h>
2727
#include <poll.h>
2828

29-
extern std::unique_ptr<FuzzedDataProvider> g_fdp;
30-
extern std::mutex g_fdp_mu;
29+
std::unique_ptr<FuzzedDataProvider> g_fdp;
30+
std::mutex g_fdp_mu;
3131

3232
std::string b64encode(const std::string &in) {
3333
static const char* tbl =
@@ -80,6 +80,14 @@ std::string safe_ascii(const std::string& in, bool allow_space) {
8080
return out;
8181
}
8282

83+
// Dummy functions
84+
static enum MHD_Bool kv_cb(void*, enum MHD_ValueKind, const struct MHD_NameAndValue*) {
85+
return MHD_YES;
86+
}
87+
static enum MHD_Bool post_cb(void*, const struct MHD_PostField* pf) {
88+
return MHD_YES;
89+
}
90+
8391
/* Start of internal helpers for sending http message to daemon through localhost socket */
8492
static int create_socket(uint16_t port) {
8593
int fd = socket(AF_INET, SOCK_STREAM, 0);
@@ -736,3 +744,58 @@ req_cb(void* cls,
736744
}
737745
return handle_digest_auth(request, opts);
738746
}
747+
748+
MHD_FN_PAR_NONNULL_(2) MHD_FN_PAR_NONNULL_(3)
749+
const struct MHD_Action*
750+
req_cb_stream(void*,
751+
struct MHD_Request* MHD_RESTRICT request,
752+
const struct MHD_String* MHD_RESTRICT path,
753+
enum MHD_HTTP_Method method,
754+
uint_fast64_t upload_size) {
755+
// Fuzz MHD_request_get_value for different parameters on random request
756+
MHD_request_get_value(request, MHD_VK_HEADER, "host");
757+
MHD_request_get_value(request, MHD_VK_HEADER, "content-type");
758+
MHD_request_get_value(request, MHD_VK_COOKIE, "cookie");
759+
MHD_request_get_value(request, MHD_VK_GET_ARGUMENT, "q");
760+
MHD_request_get_values_cb(request, MHD_VK_HEADER, kv_cb, nullptr);
761+
MHD_request_get_values_cb(request, MHD_VK_COOKIE, kv_cb, nullptr);
762+
MHD_request_get_values_cb(request, MHD_VK_GET_ARGUMENT, kv_cb, nullptr);
763+
764+
// Fuzz MHD_request_get_post_data_cb on random request
765+
MHD_request_get_post_data_cb(request, post_cb, nullptr);
766+
767+
768+
// Fuzz MHD_request_get_info_fixed for different parameters on random request
769+
union MHD_RequestInfoFixedData fix;
770+
MHD_request_get_info_fixed(request, MHD_REQUEST_INFO_FIXED_HTTP_VER, &fix);
771+
MHD_request_get_info_fixed(request, MHD_REQUEST_INFO_FIXED_HTTP_METHOD, &fix);
772+
MHD_request_get_info_fixed(request, MHD_REQUEST_INFO_FIXED_DAEMON, &fix);
773+
MHD_request_get_info_fixed(request, MHD_REQUEST_INFO_FIXED_CONNECTION, &fix);
774+
MHD_request_get_info_fixed(request, MHD_REQUEST_INFO_FIXED_STREAM, &fix);
775+
MHD_request_get_info_fixed(request, MHD_REQUEST_INFO_FIXED_APP_CONTEXT, &fix);
776+
777+
// Fuzz MHD_request_get_info_dynamic for different parameters on random request
778+
union MHD_RequestInfoDynamicData dyn;
779+
MHD_request_get_info_dynamic(request, MHD_REQUEST_INFO_DYNAMIC_HTTP_METHOD_STRING, &dyn);
780+
MHD_request_get_info_dynamic(request, MHD_REQUEST_INFO_DYNAMIC_URI, &dyn);
781+
MHD_request_get_info_dynamic(request, MHD_REQUEST_INFO_DYNAMIC_NUMBER_URI_PARAMS, &dyn);
782+
MHD_request_get_info_dynamic(request, MHD_REQUEST_INFO_DYNAMIC_NUMBER_COOKIES, &dyn);
783+
MHD_request_get_info_dynamic(request, MHD_REQUEST_INFO_DYNAMIC_HEADER_SIZE, &dyn);
784+
MHD_request_get_info_dynamic(request, MHD_REQUEST_INFO_DYNAMIC_NUMBER_POST_PARAMS, &dyn);
785+
MHD_request_get_info_dynamic(request, MHD_REQUEST_INFO_DYNAMIC_UPLOAD_PRESENT, &dyn);
786+
MHD_request_get_info_dynamic(request, MHD_REQUEST_INFO_DYNAMIC_UPLOAD_CHUNKED, &dyn);
787+
MHD_request_get_info_dynamic(request, MHD_REQUEST_INFO_DYNAMIC_UPLOAD_SIZE_TOTAL, &dyn);
788+
MHD_request_get_info_dynamic(request, MHD_REQUEST_INFO_DYNAMIC_UPLOAD_SIZE_RECIEVED, &dyn);
789+
790+
// Fuzz response creation from random request processing
791+
struct MHD_Response* resp = MHD_response_from_empty(MHD_HTTP_STATUS_NO_CONTENT);
792+
if (!resp) {
793+
return MHD_action_abort_request(request);
794+
}
795+
796+
// Fuzz response and request abortion
797+
MHD_response_add_header(resp, "x-fuzz", "values");
798+
const struct MHD_Action* act = MHD_action_from_response(request, resp);
799+
MHD_response_destroy(resp);
800+
return act ? act : MHD_action_abort_request(request);
801+
}

projects/libmicrohttpd2/mhd_helper.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,12 @@ const struct MHD_Action* req_cb(void* cls,
8282
const struct MHD_String* MHD_RESTRICT path,
8383
enum MHD_HTTP_Method method,
8484
uint_fast64_t upload_size);
85+
MHD_FN_PAR_NONNULL_(2) MHD_FN_PAR_NONNULL_(3)
86+
const struct MHD_Action* req_cb_stream(void* cls,
87+
struct MHD_Request* MHD_RESTRICT request,
88+
const struct MHD_String* MHD_RESTRICT path,
89+
enum MHD_HTTP_Method method,
90+
uint_fast64_t upload_size);
8591

8692
// Provide base64 encoding for the response/request
8793
std::string b64encode(const std::string &in);

0 commit comments

Comments
 (0)