15
15
// //////////////////////////////////////////////////////////////////////////////
16
16
#include " connection_helper.h"
17
17
#include < cstring>
18
+ #include < unordered_set>
18
19
19
20
extern " C" {
20
21
#include " mhd_action.h"
@@ -32,11 +33,30 @@ struct mhd_MemoryPool *g_pool = nullptr;
32
33
const size_t g_pool_size = 14 * 1024 ;
33
34
std::string g_mpart_boundary;
34
35
36
+ // Body status
37
+ static std::unordered_set<const MHD_Connection*> g_post_parse_ready;
38
+
35
39
// Helper to clear memory pool
36
40
void destroy_global_pool () {
37
41
if (g_pool) { mhd_pool_destroy (g_pool); g_pool = nullptr ; }
38
42
}
39
43
44
+
45
+ // Helper to set body parsing ready
46
+ void mark_post_parse_ready (MHD_Connection& c) {
47
+ g_post_parse_ready.insert (&c);
48
+ }
49
+
50
+ // Helper to check parse body status
51
+ bool is_post_parse_ready (const MHD_Connection& c) {
52
+ return g_post_parse_ready.find (&c) != g_post_parse_ready.end ();
53
+ }
54
+
55
+ // Helper to clear parse body status
56
+ void clear_post_parse_ready (const MHD_Connection& c) {
57
+ g_post_parse_ready.erase (&c);
58
+ }
59
+
40
60
// Helper to destroy error response
41
61
static bool destroy_error_response (MHD_Connection c) {
42
62
if (c.stage == mhd_HTTP_STAGE_START_REPLY) {
@@ -75,6 +95,23 @@ static std::string pick_http_version(FuzzedDataProvider& fdp) {
75
95
}
76
96
}
77
97
98
+ // Helper to check and expand buffer capcaity
99
+ bool ensure_lbuf_capacity (MHD_Connection& c, size_t min_needed) {
100
+ if (!c.daemon ) {
101
+ return false ;
102
+ }
103
+
104
+ if (c.rq .cntn .lbuf .data && c.rq .cntn .lbuf .size >= min_needed) {
105
+ return true ;
106
+ }
107
+ size_t have = c.rq .cntn .lbuf .size ;
108
+ size_t need = (min_needed > have) ? (min_needed - have) : 0 ;
109
+ if (need) {
110
+ mhd_daemon_extend_lbuf_up_to (c.daemon , need, &c.rq .cntn .lbuf );
111
+ }
112
+ return (c.rq .cntn .lbuf .data != nullptr ) && (c.rq .cntn .lbuf .size >= min_needed);
113
+ }
114
+
78
115
// Dummy upload actions
79
116
const struct MHD_UploadAction kContinueAction = {
80
117
mhd_UPLOAD_ACTION_CONTINUE, { nullptr }
@@ -101,6 +138,16 @@ dummy_done(struct MHD_Request*, void*, enum MHD_PostParseResult) {
101
138
return &kContinueAction ;
102
139
}
103
140
141
+ // Dummy request callback function
142
+ static const struct MHD_Action *
143
+ dummy_request_cb (void * cls,
144
+ struct MHD_Request * request,
145
+ const struct MHD_String * path,
146
+ enum MHD_HTTP_Method method,
147
+ uint_fast64_t upload_size) {
148
+ return nullptr ;
149
+ }
150
+
104
151
void init_daemon_connection (FuzzedDataProvider& fdp,
105
152
MHD_Daemon& d, MHD_Connection& c) {
106
153
// Basic initialisation
@@ -130,6 +177,10 @@ void init_daemon_connection(FuzzedDataProvider& fdp,
130
177
c.suspended = false ;
131
178
c.connection_timeout_ms = fdp.ConsumeIntegralInRange <uint32_t >(0 , 4096 );
132
179
c.last_activity = 0 ;
180
+
181
+ // Add dummy callback function
182
+ d.req_cfg .cb = dummy_request_cb;
183
+ d.req_cfg .cb_cls = nullptr ;
133
184
}
134
185
135
186
void init_connection_buffer (FuzzedDataProvider& fdp, MHD_Connection& c) {
@@ -268,7 +319,11 @@ void init_parsing_configuration(FuzzedDataProvider& fdp, MHD_Connection& c) {
268
319
MHD_HTTP_PostEncoding enc;
269
320
270
321
// Configure connection encoding abd methods
271
- c.rq .app_act .head_act .act = mhd_ACTION_POST_PARSE;
322
+ if (fdp.ConsumeBool ()) {
323
+ c.rq .app_act .head_act .act = mhd_ACTION_POST_PARSE;
324
+ } else {
325
+ c.rq .app_act .head_act .act = mhd_ACTION_NO_ACTION;
326
+ }
272
327
if (fdp.ConsumeBool ()) {
273
328
enc = MHD_HTTP_POST_ENCODING_TEXT_PLAIN;
274
329
} else if (fdp.ConsumeBool ()) {
@@ -366,6 +421,7 @@ void prepare_body_and_process(MHD_Connection& connection, std::string& body, siz
366
421
// Fuzz mhd_stream_prepare_for_post_parse once and mhd_stream_post_parse
367
422
mhd_stream_prepare_for_post_parse (&connection);
368
423
mhd_stream_post_parse (&connection, &body_size, &body[0 ]);
424
+ mark_post_parse_ready (connection);
369
425
} else {
370
426
// Try prepare the body by streaming connection buffer
371
427
const bool want_chunked = (connection.rq .have_chunked_upload == MHD_YES);
@@ -422,15 +478,27 @@ void prepare_body_and_process(MHD_Connection& connection, std::string& body, siz
422
478
423
479
if (staged) {
424
480
// Use stream body approach if success
425
- connection.stage = mhd_HTTP_STAGE_BODY_RECEIVING;
426
- connection.rq .have_chunked_upload = MHD_NO;
427
- connection.rq .cntn .cntn_size = (uint64_t ) body_size;
428
- mhd_stream_prepare_for_post_parse (&connection);
429
- mhd_stream_process_request_body (&connection);
481
+ const size_t min_needed = body_size + 1 ;
482
+ if (ensure_lbuf_capacity (connection, min_needed)) {
483
+ // Only post parse the request if buffer is enough
484
+ connection.stage = mhd_HTTP_STAGE_BODY_RECEIVING;
485
+ connection.rq .have_chunked_upload = MHD_NO;
486
+ connection.rq .cntn .cntn_size = (uint64_t ) body_size;
487
+ mhd_stream_prepare_for_post_parse (&connection);
488
+ mhd_stream_process_request_body (&connection);
489
+ mark_post_parse_ready (connection);
490
+ } else {
491
+ // Fall back if not enough buffer
492
+ size_t tmp = body_size;
493
+ mhd_stream_prepare_for_post_parse (&connection);
494
+ mhd_stream_post_parse (&connection, &tmp, body.data ());
495
+ mark_post_parse_ready (connection);
496
+ }
430
497
} else {
431
498
// Use post prase approach if stream body failed
432
499
mhd_stream_prepare_for_post_parse (&connection);
433
500
mhd_stream_post_parse (&connection, &body_size, &body[0 ]);
501
+ mark_post_parse_ready (connection);
434
502
}
435
503
}
436
504
}
@@ -445,4 +513,7 @@ void final_cleanup(MHD_Connection& connection, MHD_Daemon& daemon) {
445
513
if (connection.rq .cntn .lbuf .data != nullptr || connection.rq .cntn .lbuf .size != 0 ) {
446
514
mhd_daemon_free_lbuf (&daemon, &connection.rq .cntn .lbuf );
447
515
}
516
+
517
+ // Clean post parse body status
518
+ clear_post_parse_ready (connection);
448
519
}
0 commit comments