2
0
mirror of https://gitlab.isc.org/isc-projects/bind9 synced 2025-08-30 22:15:20 +00:00

Use isc_buffer_t to keep track of incoming POST data

This commit replaces the ad-hoc 64K buffer for incoming POST data with
isc_buffer_t backed by dynamically allocated buffer sized accordingly
to the value in the "Content-Length" header.
This commit is contained in:
Artem Boldariev
2021-07-21 20:10:46 +03:00
parent 0ca790d9bf
commit 6fe4ab39b9
2 changed files with 31 additions and 10 deletions

View File

@@ -536,11 +536,18 @@ on_server_data_chunk_recv_callback(int32_t stream_id, const uint8_t *data,
isc_nmsocket_h2_t *h2 = ISC_LIST_HEAD(session->sstreams);
while (h2 != NULL) {
if (stream_id == h2->stream_id) {
size_t new_bufsize = h2->bufsize + len;
if (isc_buffer_base(&h2->rbuf) == NULL) {
isc_buffer_init(
&h2->rbuf,
isc_mem_allocate(session->mctx,
h2->content_length),
MAX_DNS_MESSAGE_SIZE);
}
size_t new_bufsize = isc_buffer_usedlength(&h2->rbuf) +
len;
if (new_bufsize <= MAX_DNS_MESSAGE_SIZE &&
new_bufsize <= h2->content_length) {
memmove(h2->buf + h2->bufsize, data, len);
h2->bufsize = new_bufsize;
isc_buffer_putmem(&h2->rbuf, data, len);
break;
}
@@ -1660,6 +1667,7 @@ server_on_begin_headers_callback(nghttp2_session *ngsession,
.stream_id = frame->hd.stream_id,
.headers_error_code = ISC_HTTP_ERROR_SUCCESS
};
isc_buffer_initnull(&socket->h2.rbuf);
session->nsstreams++;
isc__nm_httpsession_attach(session, &socket->h2.session);
socket->tid = session->handle->sock->tid;
@@ -1990,8 +1998,11 @@ static struct http_error_responses {
static isc_result_t
server_send_error_response(const isc_http_error_responses_t error,
nghttp2_session *ngsession, isc_nmsocket_t *socket) {
socket->h2.bufsize = 0;
socket->h2.bufpos = 0;
void *base = isc_buffer_base(&socket->h2.rbuf);
if (base != NULL) {
isc_mem_free(socket->h2.session->mctx, base);
isc_buffer_initnull(&socket->h2.rbuf);
}
for (size_t i = 0;
i < sizeof(error_responses) / sizeof(error_responses[0]); i++)
@@ -2053,11 +2064,13 @@ server_on_request_recv(nghttp2_session *ngsession,
if (socket->h2.request_path == NULL || socket->h2.cb == NULL) {
code = ISC_HTTP_ERROR_NOT_FOUND;
} else if (socket->h2.request_type == ISC_HTTP_REQ_POST &&
socket->h2.bufsize > socket->h2.content_length)
isc_buffer_usedlength(&socket->h2.rbuf) >
socket->h2.content_length)
{
code = ISC_HTTP_ERROR_PAYLOAD_TOO_LARGE;
} else if (socket->h2.request_type == ISC_HTTP_REQ_POST &&
socket->h2.bufsize != socket->h2.content_length)
isc_buffer_usedlength(&socket->h2.rbuf) !=
socket->h2.content_length)
{
code = ISC_HTTP_ERROR_BAD_REQUEST;
}
@@ -2079,7 +2092,7 @@ server_on_request_recv(nghttp2_session *ngsession,
isc__buffer_usedregion(&decoded_buf, &data);
} else if (socket->h2.request_type == ISC_HTTP_REQ_POST) {
INSIST(socket->h2.content_length > 0);
data = (isc_region_t){ socket->h2.buf, socket->h2.bufsize };
isc_buffer_usedregion(&socket->h2.rbuf, &data);
} else {
INSIST(0);
ISC_UNREACHABLE();
@@ -2734,6 +2747,7 @@ isc__nm_async_httpclose(isc__networker_t *worker, isc__netievent_t *ev0) {
static void
failed_httpstream_read_cb(isc_nmsocket_t *sock, isc_result_t result,
isc_nm_http_session_t *session) {
isc_region_t data;
REQUIRE(VALID_NMSOCK(sock));
INSIST(sock->type == isc_nm_httpsocket);
@@ -2746,8 +2760,8 @@ failed_httpstream_read_cb(isc_nmsocket_t *sock, isc_result_t result,
(void)nghttp2_submit_rst_stream(
session->ngsession, NGHTTP2_FLAG_END_STREAM, sock->h2.stream_id,
NGHTTP2_REFUSED_STREAM);
server_call_cb(sock, session, result,
&(isc_region_t){ sock->h2.buf, sock->h2.bufsize });
isc_buffer_usedregion(&sock->h2.rbuf, &data);
server_call_cb(sock, session, result, &data);
}
static void
@@ -3015,6 +3029,12 @@ isc__nm_http_cleanup_data(isc_nmsocket_t *sock) {
isc_mem_free(sock->mgr->mctx, sock->h2.buf);
sock->h2.buf = NULL;
}
if (isc_buffer_base(&sock->h2.rbuf) != NULL) {
void *base = isc_buffer_base(&sock->h2.rbuf);
isc_mem_free(sock->mgr->mctx, base);
isc_buffer_initnull(&sock->h2.rbuf);
}
}
if ((sock->type == isc_nm_httplistener ||

View File

@@ -803,6 +803,7 @@ typedef struct isc_nmsocket_h2 {
uint8_t *buf;
size_t bufsize;
size_t bufpos;
isc_buffer_t rbuf;
int32_t stream_id;
isc_nm_http_session_t *session;