diff --git a/src/mhd2/daemon_funcs.c b/src/mhd2/daemon_funcs.c index 523a6884..60159a05 100644 --- a/src/mhd2/daemon_funcs.c +++ b/src/mhd2/daemon_funcs.c @@ -99,6 +99,33 @@ mhd_daemon_claim_lbuf (struct MHD_Daemon *d, } +static MHD_FN_PAR_NONNULL_ALL_ +MHD_FN_MUST_CHECK_RESULT_ size_t +mhd_daemon_claim_lbuf_up_to (struct MHD_Daemon *d, + size_t requested_size) +{ + size_t ret; + struct MHD_Daemon *const masterd = mhd_daemon_get_master_daemon (d); + mhd_assert (0 != requested_size); + if (0 == masterd->req_cfg.large_buf.space_left) + return false; /* Shortcut for typical use without large buffer */ + + mhd_mutex_lock_chk (&(masterd->req_cfg.large_buf.lock)); + if (masterd->req_cfg.large_buf.space_left >= requested_size) + { + ret = requested_size; + masterd->req_cfg.large_buf.space_left -= requested_size; + } + else + { + ret = masterd->req_cfg.large_buf.space_left; + masterd->req_cfg.large_buf.space_left = 0; + } + mhd_mutex_unlock_chk (&(masterd->req_cfg.large_buf.lock)); + return ret; +} + + MHD_INTERNAL MHD_FN_PAR_NONNULL_ALL_ void mhd_daemon_reclaim_lbuf (struct MHD_Daemon *d, size_t reclaimed_size) @@ -165,6 +192,59 @@ mhd_daemon_grow_lbuf (struct MHD_Daemon *restrict d, } +MHD_INTERNAL MHD_FN_PAR_NONNULL_ALL_ MHD_FN_MUST_CHECK_RESULT_ +MHD_FN_PAR_INOUT_ (3) size_t +mhd_daemon_extend_lbuf_up_to (struct MHD_Daemon *restrict d, + size_t desired_grow_size, + struct mhd_Buffer *restrict buf) +{ + void *new_alloc; + size_t grow_size; + mhd_assert (NULL != buf->data || 0 == buf->size); + mhd_assert (0 != buf->size || NULL == buf->data); + + grow_size = mhd_daemon_claim_lbuf_up_to (d, desired_grow_size); + + new_alloc = NULL; + if (NULL == buf->data) + { + while ((0 != grow_size) && + (NULL == (new_alloc = malloc (grow_size)))) + { + size_t reduce = grow_size / 2; + if (sizeof(void *) >= (grow_size - reduce)) + reduce = grow_size; + mhd_daemon_reclaim_lbuf (d, + reduce); + grow_size -= reduce; + } + } + else + { + while ((0 != grow_size) && + (NULL == (new_alloc = realloc (buf->data, + buf->size + grow_size)))) + { + size_t reduce = grow_size / 2; + if (sizeof(void *) >= (grow_size - reduce)) + reduce = grow_size; + mhd_daemon_reclaim_lbuf (d, + reduce); + grow_size -= reduce; + } + } + + if (NULL != new_alloc) + { + mhd_assert (0 != grow_size); + buf->data = new_alloc; + buf->size += grow_size; + } + + return grow_size; +} + + MHD_INTERNAL MHD_FN_PAR_NONNULL_ALL_ MHD_FN_PAR_INOUT_ (2) void mhd_daemon_free_lbuf (struct MHD_Daemon *restrict d, diff --git a/src/mhd2/daemon_funcs.h b/src/mhd2/daemon_funcs.h index 73cc3a79..2f6ae801 100644 --- a/src/mhd2/daemon_funcs.h +++ b/src/mhd2/daemon_funcs.h @@ -123,6 +123,22 @@ mhd_daemon_grow_lbuf (struct MHD_Daemon *restrict d, MHD_FN_PAR_NONNULL_ALL_ MHD_FN_MUST_CHECK_RESULT_ MHD_FN_PAR_INOUT_ (3); +/** + * Grow or allocate the large buffer up to specified grow size. + * If the requested grow size is not possible, grow up to max possible size. + * @param d the daemon to use + * @param desired_grow_size the desired size of grow + * @param[in,out] buf the buffer to grow, must be allocated previously or + * zero-initialised + * @return the resulting grow size + */ +MHD_INTERNAL size_t +mhd_daemon_extend_lbuf_up_to (struct MHD_Daemon *restrict d, + size_t desired_grow_size, + struct mhd_Buffer *restrict buf) +MHD_FN_PAR_NONNULL_ALL_ MHD_FN_MUST_CHECK_RESULT_ + MHD_FN_PAR_INOUT_ (3); + /** * Free large buffer. diff --git a/src/mhd2/mhd_post_parser.h b/src/mhd2/mhd_post_parser.h index 267f9760..3e70cd3b 100644 --- a/src/mhd2/mhd_post_parser.h +++ b/src/mhd2/mhd_post_parser.h @@ -242,7 +242,7 @@ enum MHD_FIXED_ENUM_ mhd_PostMPartState * Check for delimiter failed, continuing processing of the "value" * This is an intermediate state, should be processed and switched to the next * state immediately. - * Should not be used outside processing loop. + * Can be used outside processing loop if streaming partial value. */ mhd_POST_MPART_ST_BACK_TO_VALUE , @@ -623,7 +623,12 @@ struct mhd_PostParserData size_t field_start; /** - * The offset in the value data. + * 'true' if current filed 'value' must be "streamed". + */ + bool force_streamed; + + /** + * The offset in the current value data. * Used when value is processed incrementally otherwise it is zero. */ size_t value_off; diff --git a/src/mhd2/post_parser_funcs.c b/src/mhd2/post_parser_funcs.c index 56f18a17..d70acc9a 100644 --- a/src/mhd2/post_parser_funcs.c +++ b/src/mhd2/post_parser_funcs.c @@ -446,6 +446,8 @@ mhd_stream_prepare_for_post_parse (struct MHD_Connection *restrict c) } +#if 0 /* Disable unused functions */ + /** * Allocate memory from "large shared buffer" for POST parsing * @param c the stream to use @@ -501,6 +503,54 @@ grow_lbuf_fixed_size (struct MHD_Connection *restrict c, } +#endif /* Disable unused functions */ + +/** + * Grow or allocate the new memory from "large shared buffer" for POST parsing + * If the requested grow size is not possible, grow up to max possible size. + * @param c the stream to use + * @param desired_grow_size the desired size to grow + * @param[in,out] buf the buffer to grow + * @return the resulting grow size + */ +static MHD_FN_PAR_NONNULL_ALL_ +MHD_FN_PAR_INOUT_ (3) size_t +extend_lbuf_up_to (struct MHD_Connection *restrict c, + size_t desired_grow_size, + struct mhd_Buffer *restrict buf) +{ + mhd_assert (mhd_ACTION_POST_PARSE == c->rq.app_act.head_act.act); + mhd_assert (c->rq.u_proc.post.lbuf_limit >= buf->size); + + if (buf->size + desired_grow_size > c->rq.u_proc.post.lbuf_limit) + desired_grow_size = c->rq.u_proc.post.lbuf_limit - buf->size; + + return mhd_daemon_extend_lbuf_up_to (c->daemon, + desired_grow_size, + buf); +} + + +static MHD_FN_PAR_NONNULL_ALL_ bool +report_low_lbuf_mem (struct MHD_Connection *restrict c) +{ + mhd_LOG_MSG (c->daemon, \ + MHD_SC_REQ_POST_PARSE_FAILED_NO_LARGE_BUF_MEM, \ + "Not enough large shared buffer memory to " \ + "parse POST request."); + c->rq.u_proc.post.parse_result = + MHD_POST_PARSE_RES_FAILED_NO_LARGE_BUF_MEM; + if (c->state < MHD_CONNECTION_FULL_REQ_RECEIVED) + { + c->discard_request = true; + c->state = MHD_CONNECTION_FULL_REQ_RECEIVED; + + return true; + } + return false; +} + + /** * Test whether current incomplete value must be provided to the "stream" * reader. @@ -520,13 +570,16 @@ is_value_streaming_needed (struct MHD_Connection *restrict c, if (NULL == p_par->stream_reader) { mhd_assert (0 == p_data->value_off); + mhd_assert (! p_data->force_streamed); return false; /* No value streaming possible */ } - if (0 != p_data->value_off) - return true; /* Part of the value has been already provided to "stream" - reader, the rest of the value should be provided - in the same way */ + /* If part of the value has been already provided to "stream" + reader, the rest of the value should be provided + in the same way */ + mhd_assert ((0 == p_data->value_off) || p_data->force_streamed); + if (p_data->force_streamed) + return true; return (p_par->max_nonstream_size < field_cur_size); } @@ -721,6 +774,7 @@ process_complete_field_all (struct MHD_Connection *restrict c, mhd_assert ((0 != cntn_type_start) || (0 == cntn_type_len)); mhd_assert ((0 != enc_start) || (0 == enc_len)); mhd_assert ((0 != value_start) || (0 == value_len)); + mhd_assert (0 == buf [name_start + name_len]); p_data->some_data_provided = true; @@ -762,6 +816,7 @@ process_complete_field_all (struct MHD_Connection *restrict c, res = mhd_stream_process_upload_action (c, act, false); if (c->suspended) return true; + p_data->force_streamed = false; p_data->value_off = 0; if (*pdata_size > *pfield_next_pos) { @@ -781,6 +836,10 @@ process_complete_field_all (struct MHD_Connection *restrict c, struct mhd_PositionAndLength encoding_i; struct mhd_PositionAndLength value_i; + mhd_assert (! p_data->force_streamed); + mhd_assert (0 == p_data->value_off); + mhd_assert ((0 == value_start) || (0 == buf [value_start + value_len])); + name_i.pos = name_start; name_i.len = name_len; filename_i.pos = filename_start; @@ -971,6 +1030,7 @@ process_partial_value_all (struct MHD_Connection *restrict c, MHD_NO); p_data->some_data_provided = true; + p_data->force_streamed = true; res = mhd_stream_process_upload_action (c, act, false); if (c->suspended) @@ -1745,9 +1805,9 @@ parse_post_mpart (struct MHD_Connection *restrict c, mhd_assert (0 != mf->f.name_len); mhd_assert (i > mf->f.name_idx); mf->f.value_idx = i; - mf->line_start = mhd_POST_INVALID_POS; /* Intentional fall-through */ case mhd_POST_MPART_ST_BACK_TO_VALUE: + mf->line_start = mhd_POST_INVALID_POS; mf->delim_check_start = mhd_POST_INVALID_POS; mf->st = mhd_POST_MPART_ST_VALUE; /* Intentional fall-through */ @@ -2001,9 +2061,7 @@ parse_post_mpart (struct MHD_Connection *restrict c, if (mhd_POST_MPART_ST_VALUE != mf->st) { i = mf->delim_check_start; /* Reset position */ - mf->delim_check_start = mhd_POST_INVALID_POS; - mf->line_start = mhd_POST_INVALID_POS; - mf->st = mhd_POST_MPART_ST_VALUE; + mf->st = mhd_POST_MPART_ST_BACK_TO_VALUE; } proc_res = @@ -2257,7 +2315,7 @@ mhd_stream_post_parse (struct MHD_Connection *restrict c, char *restrict buf) { struct mhd_PostParserData *const p_data = &(c->rq.u_proc.post); - bool alloc_failed; + size_t lbuf_left; mhd_assert (MHD_HTTP_POST_ENCODING_OTHER != p_data->enc); mhd_assert (c->rq.cntn.lbuf.size <= p_data->lbuf_limit); @@ -2266,75 +2324,74 @@ mhd_stream_post_parse (struct MHD_Connection *restrict c, (mhd_POST_MPART_ST_EPILOGUE == p_data->e_d.m_form.st)) { /* No need to process the data */ - *pdata_size = 0; /* All data has been moved */ + *pdata_size = 0; /* All data has been "processed" */ return false; /* Continue normal processing */ } // TODO: support process in the connection buffer - if (NULL == c->rq.cntn.lbuf.data) - { - alloc_failed = ! get_lbuf_fixed_size (c, - *pdata_size + 1, - &(c->rq.cntn.lbuf)); - } - else - { - size_t space_left; - mhd_assert (c->rq.cntn.lbuf.size >= p_data->lbuf_used); - space_left = c->rq.cntn.lbuf.size - p_data->lbuf_used; + mhd_assert (c->rq.cntn.lbuf.size >= p_data->lbuf_used); + lbuf_left = c->rq.cntn.lbuf.size - p_data->lbuf_used; - if (*pdata_size > space_left) - alloc_failed = ! grow_lbuf_fixed_size (c, - *pdata_size - space_left + 1, - &(c->rq.cntn.lbuf)); - else - alloc_failed = false; + if (*pdata_size + 1 > lbuf_left) + (void) extend_lbuf_up_to (c, + *pdata_size + 1 - lbuf_left, + &(c->rq.cntn.lbuf)); - } - if (alloc_failed) + while ((0 != *pdata_size) && + (c->rq.cntn.lbuf.size > p_data->lbuf_used)) { - mhd_LOG_MSG (c->daemon, \ - MHD_SC_REQ_POST_PARSE_FAILED_NO_LARGE_BUF_MEM, \ - "Not enough large shared buffer memory to " \ - "parse POST request."); - p_data->parse_result = - MHD_POST_PARSE_RES_FAILED_NO_LARGE_BUF_MEM; - c->discard_request = true; - c->state = MHD_CONNECTION_FULL_REQ_RECEIVED; - return true; - } - memcpy (c->rq.cntn.lbuf.data + p_data->lbuf_used, - buf, - *pdata_size); - p_data->lbuf_used += *pdata_size; - *pdata_size = 0; /* All data has been moved */ + size_t data_size_before_parse; + size_t copy_size = *pdata_size; + lbuf_left = c->rq.cntn.lbuf.size - p_data->lbuf_used; + if (lbuf_left < copy_size) + copy_size = lbuf_left; - switch (p_data->enc) - { - case MHD_HTTP_POST_ENCODING_FORM_URLENCODED: - return parse_post_urlenc (c, - &(p_data->lbuf_used), - c->rq.cntn.lbuf.data); - case MHD_HTTP_POST_ENCODING_MULTIPART_FORMDATA: - return parse_post_mpart (c, + memcpy (c->rq.cntn.lbuf.data + p_data->lbuf_used, + buf, + copy_size); + p_data->lbuf_used += copy_size; + *pdata_size -= copy_size; + + data_size_before_parse = p_data->lbuf_used; + switch (p_data->enc) + { + case MHD_HTTP_POST_ENCODING_FORM_URLENCODED: + if (parse_post_urlenc (c, &(p_data->lbuf_used), - c->rq.cntn.lbuf.data); - case MHD_HTTP_POST_ENCODING_TEXT_PLAIN: - return parse_post_text (c, + c->rq.cntn.lbuf.data)) + return true; + break; + case MHD_HTTP_POST_ENCODING_MULTIPART_FORMDATA: + if (parse_post_mpart (c, &(p_data->lbuf_used), - c->rq.cntn.lbuf.data); - case MHD_HTTP_POST_ENCODING_OTHER: - default: - mhd_assert (0 && "Impossible value"); - MHD_UNREACHABLE_; - p_data->parse_result = - MHD_POST_PARSE_RES_PARTIAL_INVALID_POST_FORMAT; - c->discard_request = true; - c->state = MHD_CONNECTION_FULL_REQ_RECEIVED; - break; + c->rq.cntn.lbuf.data)) + return true; + break; + case MHD_HTTP_POST_ENCODING_TEXT_PLAIN: + if (parse_post_text (c, + &(p_data->lbuf_used), + c->rq.cntn.lbuf.data)) + return true; + break; + case MHD_HTTP_POST_ENCODING_OTHER: + default: + mhd_assert (0 && "Impossible value"); + MHD_UNREACHABLE_; + p_data->parse_result = + MHD_POST_PARSE_RES_PARTIAL_INVALID_POST_FORMAT; + c->discard_request = true; + c->state = MHD_CONNECTION_FULL_REQ_RECEIVED; + return true; + } + if (data_size_before_parse == p_data->lbuf_used) + break; /* Nothing consumed, not possible to add new data to the buffer now */ } - return true; + + if (0 != *pdata_size) + return report_low_lbuf_mem (c); + + return false; /* Continue normal processing */ } @@ -2360,11 +2417,16 @@ check_post_leftovers_urlenc (struct MHD_Connection *restrict c, size_t name_len; size_t value_start; size_t value_len; + bool need_more_space; + bool have_extra_space; + bool need_value_stream; - pos = p_data->next_parse_pos; /* Points to the char AFTER the data, valid location as buffer is always at least one byte larger */ - mhd_assert (pos == p_data->next_parse_pos); - mhd_assert (pos < c->rq.cntn.lbuf.size); // TODO: support processing in connection buffer + pos = p_data->next_parse_pos; /* Points to the char AFTER the data */ + mhd_assert (pos <= c->rq.cntn.lbuf.size); // TODO: support processing in connection buffer mhd_assert (*pdata_size >= pos); + have_extra_space = (pos < c->rq.cntn.lbuf.size); + need_more_space = false; /**< No space for zero termination */ + need_value_stream = false; /**< Value cannot be zero-terminated and must be streamed */ switch (uf->st) { case mhd_POST_UENC_ST_NOT_STARTED: @@ -2382,9 +2444,16 @@ check_post_leftovers_urlenc (struct MHD_Connection *restrict c, NULL); else name_len = pos - uf->name_idx; - buf[name_start + name_len] = 0; /* Zero-terminate the result, an extra byte is always available in the buffer */ - value_start = 0; - value_len = 0; + mhd_assert (name_start + name_len <= pos); + if (! have_extra_space && + (name_start + name_len == pos)) + need_more_space = true; + else + { + buf[name_start + name_len] = 0; /* Zero-terminate the result, an extra byte is available */ + value_start = 0; + value_len = 0; + } break; case mhd_POST_UENC_ST_EQ_FOUND: mhd_assert (pos == *pdata_size); @@ -2392,7 +2461,10 @@ check_post_leftovers_urlenc (struct MHD_Connection *restrict c, name_len = uf->name_len; value_start = pos; value_len = 0; - buf[value_start] = 0; /* Zero-terminate the result, an extra byte is always available */ + if (! have_extra_space) + need_value_stream = true; + else + buf[value_start] = 0; /* Zero-terminate the result, an extra byte is available */ break; case mhd_POST_UENC_ST_VALUE: mhd_assert (0 != uf->value_idx); @@ -2426,7 +2498,11 @@ check_post_leftovers_urlenc (struct MHD_Connection *restrict c, else value_len = pos - uf->value_idx; } - buf[value_start + value_len] = 0; /* Zero-terminate the result, an extra byte is always available in the buffer */ + if (! have_extra_space && + (value_start + value_len == pos)) + need_value_stream = true; + else + buf[value_start + value_len] = 0; /* Zero-terminate the result, an extra byte is available in the buffer */ break; case mhd_POST_UENC_ST_FULL_FIELD_FOUND: /* Full value was found, but the stream has been suspended by @@ -2452,9 +2528,24 @@ check_post_leftovers_urlenc (struct MHD_Connection *restrict c, return false; } + /* Have field data */ + + p_data->next_parse_pos = pos; + + if (need_value_stream) + { + if (NULL != c->rq.app_act.head_act.data.post_parse.stream_reader) + p_data->force_streamed = true; + else + need_more_space = true; + } + + if (need_more_space) + return report_low_lbuf_mem (c); + if (process_complete_field (c, buf, - &pos, + &(p_data->next_parse_pos), pdata_size, p_data->field_start, name_start, @@ -2489,18 +2580,17 @@ check_post_leftovers_mpart (struct MHD_Connection *restrict c, size_t pos; bool not_terminated; bool add_field; - size_t field_pos; - size_t field_len; + size_t value_pos; + size_t value_len; pos = p_data->next_parse_pos; /* Points to the char AFTER the data, valid location as buffer is always at least one byte larger */ - mhd_assert (pos == p_data->next_parse_pos); - mhd_assert (pos < c->rq.cntn.lbuf.size); // TODO: support processing in connection buffer + mhd_assert (pos <= c->rq.cntn.lbuf.size); // TODO: support processing in connection buffer mhd_assert (*pdata_size >= pos); not_terminated = false; add_field = false; - field_pos = 0; - field_len = 0; + value_pos = 0; + value_len = 0; switch (mf->st) { @@ -2532,8 +2622,8 @@ check_post_leftovers_mpart (struct MHD_Connection *restrict c, mhd_assert (0 != mf->f.value_idx); not_terminated = true; add_field = true; - field_pos = mf->f.value_idx; - field_len = pos - field_len; + value_pos = mf->f.value_idx; + value_len = pos - value_len; break; case mhd_POST_MPART_ST_DELIM_FOUND: mhd_assert (0 != mf->f.name_idx); @@ -2543,8 +2633,8 @@ check_post_leftovers_mpart (struct MHD_Connection *restrict c, add_field = true; if (0 != mf->f.value_idx) { - field_pos = mf->f.value_idx; - field_len = pos - mf->delim_check_start; + value_pos = mf->f.value_idx; + value_len = pos - mf->delim_check_start; } break; case mhd_POST_MPART_ST_FULL_FIELD_FOUND: @@ -2555,8 +2645,8 @@ check_post_leftovers_mpart (struct MHD_Connection *restrict c, add_field = true; if (0 != mf->f.value_idx) { - field_pos = mf->f.value_idx; - field_len = mf->f.value_len; + value_pos = mf->f.value_idx; + value_len = mf->f.value_len; } break; case mhd_POST_MPART_ST_EPILOGUE: @@ -2587,9 +2677,18 @@ check_post_leftovers_mpart (struct MHD_Connection *restrict c, if (add_field) { + if (c->rq.cntn.lbuf.size > (value_pos + value_len)) + buf [value_pos + value_len] = 0; /* Zero-terminate the value */ + else if (NULL != c->rq.app_act.head_act.data.post_parse.stream_reader) + p_data->force_streamed = true; + else + return report_low_lbuf_mem (c); + + p_data->next_parse_pos = pos; + if (process_complete_field_all (c, buf, - &pos, + &p_data->next_parse_pos, pdata_size, p_data->field_start, mf->f.name_idx, @@ -2600,8 +2699,8 @@ check_post_leftovers_mpart (struct MHD_Connection *restrict c, mf->f.cntn_type_len, mf->f.enc_idx, mf->f.enc_len, - field_pos, - field_len)) + value_pos, + value_len)) return true; } @@ -2636,8 +2735,7 @@ check_post_leftovers_text (struct MHD_Connection *restrict c, size_t value_len; pos = p_data->next_parse_pos; /* Points to the char AFTER the data, valid location as buffer is always at least one byte larger */ - mhd_assert (pos == p_data->next_parse_pos); - mhd_assert (pos < c->rq.cntn.lbuf.size); // TODO: support processing in connection buffer + mhd_assert (pos <= c->rq.cntn.lbuf.size); // TODO: support processing in connection buffer switch (tf->st) { case mhd_POST_TEXT_ST_NOT_STARTED: @@ -2648,7 +2746,9 @@ check_post_leftovers_text (struct MHD_Connection *restrict c, mhd_assert (pos == *pdata_size); name_start = tf->name_idx; name_len = pos - name_start; - buf[pos] = 0; /* Zero-terminate the result, an extra byte is always available */ + if (pos == c->rq.cntn.lbuf.size) + return report_low_lbuf_mem (c); + buf[pos] = 0; /* Zero-terminate the result, an extra byte is available */ value_start = 0; value_len = 0; break; @@ -2716,6 +2816,16 @@ check_post_leftovers_text (struct MHD_Connection *restrict c, p_data->parse_result = MHD_POST_PARSE_RES_OK_BAD_TERMINATION; } + if (0 != value_start) + { + if (c->rq.cntn.lbuf.size > (value_start + value_len)) + buf [value_start + value_len] = 0; /* Zero-terminate the value */ + else if (NULL != c->rq.app_act.head_act.data.post_parse.stream_reader) + p_data->force_streamed = true; + else + return report_low_lbuf_mem (c); + } + if (process_complete_field (c, buf, &pos, @@ -2743,6 +2853,12 @@ static MHD_FN_PAR_NONNULL_ALL_ bool check_post_leftovers (struct MHD_Connection *restrict c) { struct mhd_PostParserData *const p_data = &(c->rq.u_proc.post); + // TODO: implement processing in the connection buffer + if (p_data->lbuf_used == c->rq.cntn.lbuf.size) + (void) extend_lbuf_up_to (c, + 1, + &(c->rq.cntn.lbuf)); + switch (p_data->enc) { case MHD_HTTP_POST_ENCODING_FORM_URLENCODED: diff --git a/src/mhd2/stream_process_request.c b/src/mhd2/stream_process_request.c index 70d3ad12..ff2a9d8e 100644 --- a/src/mhd2/stream_process_request.c +++ b/src/mhd2/stream_process_request.c @@ -3258,9 +3258,11 @@ process_request_chunked_body (struct MHD_Connection *restrict c) state_updated = mhd_stream_post_parse (c, &cntn_data_ready, buffer_head); - mhd_assert (0 == cntn_data_ready); // TODO: support one chunk in-place processing? + // TODO: support one chunk in-place processing? + mhd_assert ((0 == cntn_data_ready) || \ + (MHD_POST_PARSE_RES_OK != c->rq.u_proc.post.parse_result) || \ + (MHD_CONNECTION_BODY_RECEIVING != c->state)); c->rq.cntn.recv_size += size_provided; - } else #endif /* HAVE_POST_PARSER */ @@ -3389,7 +3391,9 @@ process_request_nonchunked_body (struct MHD_Connection *restrict c) state_updated = mhd_stream_post_parse (c, &size_provided, c->read_buffer); - mhd_assert (0 == size_provided); + mhd_assert ((0 == size_provided) || \ + (MHD_POST_PARSE_RES_OK != c->rq.u_proc.post.parse_result) || \ + (MHD_CONNECTION_BODY_RECEIVING != c->state)); read_buf_reuse = true; c->rq.cntn.proc_size += cntn_data_ready; if (c->rq.cntn.recv_size == c->rq.cntn.cntn_size)