Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion include/h2o/http2_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@
#define H2O_HTTP2_ERROR_ENHANCE_YOUR_CALM -11
#define H2O_HTTP2_ERROR_INADEQUATE_SECURITY -12
#define H2O_HTTP2_ERROR_MAX 13
/* end of the HTT2-spec defined errors */
/* end of the HTTP2-spec defined errors */
#define H2O_HTTP2_ERROR_INVALID_HEADER_CHAR \
-254 /* an internal value indicating that invalid characters were found in the header name or value */
#define H2O_HTTP2_ERROR_INCOMPLETE -255 /* an internal value indicating that all data is not ready */
Expand Down
24 changes: 21 additions & 3 deletions include/h2o/memory.h
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,11 @@ void h2o_buffer__do_free(h2o_buffer_t *buffer);
* disposes of the buffer
*/
static void h2o_buffer_dispose(h2o_buffer_t **buffer);
/**
* allocates a buffer with h2o_buffer_try_reserve. aborts on allocation failure.
* @return buffer to which the next data should be stored
*/
h2o_iovec_t h2o_buffer_reserve(h2o_buffer_t **inbuf, size_t min_guarantee);
/**
* allocates a buffer.
* @param inbuf - pointer to a pointer pointing to the structure (set *inbuf to NULL to allocate a new buffer)
Expand All @@ -264,12 +269,17 @@ static void h2o_buffer_dispose(h2o_buffer_t **buffer);
* @note When called against a new buffer, the function returns a buffer twice the size of requested guarantee. The function uses
* exponential backoff for already-allocated buffers.
*/
h2o_iovec_t h2o_buffer_reserve(h2o_buffer_t **inbuf, size_t min_guarantee);
h2o_iovec_t h2o_buffer_try_reserve(h2o_buffer_t **inbuf, size_t min_guarantee) __attribute__((warn_unused_result));
/**
* copies @len bytes from @src to @dst, calling h2o_buffer_reserve
* @return 0 if the allocation failed, 1 otherwise
* copies @len bytes from @src to @dst, calling h2o_buffer_reserve. aborts on allocation failure.
* @return 1 on successful allocation
*/
static int h2o_buffer_append(h2o_buffer_t **dst, void *src, size_t len);
/**
* variant of h2o_buffer_append that does not abort on failure
* @return 0 on allocation failure, 1 otherwise
*/
static int h2o_buffer_try_append(h2o_buffer_t **dst, void *src, size_t len);
/**
* throws away given size of the data from the buffer.
* @param delta number of octets to be drained from the buffer
Expand Down Expand Up @@ -431,6 +441,14 @@ inline void h2o_buffer_link_to_pool(h2o_buffer_t *buffer, h2o_mem_pool_t *pool)
inline int h2o_buffer_append(h2o_buffer_t **dst, void *src, size_t len)
{
h2o_iovec_t buf = h2o_buffer_reserve(dst, len);
h2o_memcpy(buf.base, src, len);
(*dst)->size += len;
return 1;
}

inline int h2o_buffer_try_append(h2o_buffer_t **dst, void *src, size_t len)
{
h2o_iovec_t buf = h2o_buffer_try_reserve(dst, len);
if (buf.base == NULL)
return 0;
h2o_memcpy(buf.base, src, len);
Expand Down
9 changes: 9 additions & 0 deletions lib/common/memory.c
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,15 @@ void h2o_buffer__do_free(h2o_buffer_t *buffer)
}

h2o_iovec_t h2o_buffer_reserve(h2o_buffer_t **_inbuf, size_t min_guarantee)
{
h2o_iovec_t reserved = h2o_buffer_try_reserve(_inbuf, min_guarantee);
if (reserved.base == NULL) {
h2o_fatal("failed to reserve buffer; capacity: %zu, min_gurantee: %zu", (*_inbuf)->capacity, min_guarantee);
}
return reserved;
}

h2o_iovec_t h2o_buffer_try_reserve(h2o_buffer_t **_inbuf, size_t min_guarantee)
{
h2o_buffer_t *inbuf = *_inbuf;
h2o_iovec_t ret;
Expand Down
6 changes: 3 additions & 3 deletions lib/common/socket.c
Original file line number Diff line number Diff line change
Expand Up @@ -247,7 +247,7 @@ const char *decode_ssl_input(h2o_socket_t *sock)
h2o_iovec_t reserved;
ptls_buffer_t rbuf;
int ret;
if ((reserved = h2o_buffer_reserve(&sock->input, sock->ssl->input.encrypted->size)).base == NULL)
if ((reserved = h2o_buffer_try_reserve(&sock->input, sock->ssl->input.encrypted->size)).base == NULL)
return h2o_socket_error_out_of_memory;
ptls_buffer_init(&rbuf, reserved.base, reserved.len);
do {
Expand All @@ -258,7 +258,7 @@ const char *decode_ssl_input(h2o_socket_t *sock)
} while (src != src_end);
h2o_buffer_consume(&sock->ssl->input.encrypted, sock->ssl->input.encrypted->size - (src_end - src));
if (rbuf.is_allocated) {
if ((reserved = h2o_buffer_reserve(&sock->input, rbuf.off)).base == NULL)
if ((reserved = h2o_buffer_try_reserve(&sock->input, rbuf.off)).base == NULL)
return h2o_socket_error_out_of_memory;
memcpy(reserved.base, rbuf.base, rbuf.off);
sock->input->size += rbuf.off;
Expand All @@ -275,7 +275,7 @@ const char *decode_ssl_input(h2o_socket_t *sock)

while (sock->ssl->input.encrypted->size != 0 || SSL_pending(sock->ssl->ossl)) {
int rlen;
h2o_iovec_t buf = h2o_buffer_reserve(&sock->input, 4096);
h2o_iovec_t buf = h2o_buffer_try_reserve(&sock->input, 4096);
if (buf.base == NULL)
return h2o_socket_error_out_of_memory;
{ /* call SSL_read (while detecting SSL renegotiation and reporting it as error) */
Expand Down
2 changes: 1 addition & 1 deletion lib/common/socket/evloop.c.h
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ static const char *on_read_core(int fd, h2o_buffer_t **input)

while (1) {
ssize_t rret;
h2o_iovec_t buf = h2o_buffer_reserve(input, 4096);
h2o_iovec_t buf = h2o_buffer_try_reserve(input, 4096);
if (buf.base == NULL) {
/* memory allocation failed */
return h2o_socket_error_out_of_memory;
Expand Down
4 changes: 2 additions & 2 deletions lib/common/socket/uv-binding.c.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,15 +41,15 @@ static void alloc_inbuf_tcp(uv_handle_t *handle, size_t suggested_size, uv_buf_t
{
struct st_h2o_uv_socket_t *sock = handle->data;

h2o_iovec_t buf = h2o_buffer_reserve(&sock->super.input, 4096);
h2o_iovec_t buf = h2o_buffer_try_reserve(&sock->super.input, 4096);
memcpy(_buf, &buf, sizeof(buf));
}

static void alloc_inbuf_ssl(uv_handle_t *handle, size_t suggested_size, uv_buf_t *_buf)
{
struct st_h2o_uv_socket_t *sock = handle->data;

h2o_iovec_t buf = h2o_buffer_reserve(&sock->super.ssl->input.encrypted, 4096);
h2o_iovec_t buf = h2o_buffer_try_reserve(&sock->super.ssl->input.encrypted, 4096);
memcpy(_buf, &buf, sizeof(buf));
}

Expand Down
21 changes: 15 additions & 6 deletions lib/handler/fastcgi.c
Original file line number Diff line number Diff line change
Expand Up @@ -551,21 +551,24 @@ static int fill_headers(h2o_req_t *req, struct phr_header *headers, size_t num_h
return 0;
}

static void append_content(struct st_fcgi_generator_t *generator, const void *src, size_t len)
static int append_content(struct st_fcgi_generator_t *generator, const void *src, size_t len)
{
/* do not accumulate more than content-length bytes */
if (generator->leftsize != SIZE_MAX) {
if (generator->leftsize < len) {
len = generator->leftsize;
if (len == 0)
return;
return 0;
}
generator->leftsize -= len;
}

h2o_iovec_t reserved = h2o_buffer_reserve(&generator->resp.receiving, len);
h2o_iovec_t reserved = h2o_buffer_try_reserve(&generator->resp.receiving, len);
if (reserved.base == NULL) {
return -1;
}
memcpy(reserved.base, src, len);
generator->resp.receiving->size += len;
return 0;
}

static int handle_stdin_record(struct st_fcgi_generator_t *generator, struct st_fcgi_record_header_t *header)
Expand All @@ -580,7 +583,10 @@ static int handle_stdin_record(struct st_fcgi_generator_t *generator, struct st_

if (generator->sent_headers) {
/* simply accumulate the data to response buffer */
append_content(generator, input->bytes + FCGI_RECORD_HEADER_SIZE, header->contentLength);
if (append_content(generator, input->bytes + FCGI_RECORD_HEADER_SIZE, header->contentLength) != 0) {
h2o_req_log_error(generator->req, MODULE_NAME, "failed to allocate memory");
return -1;
}
return 0;
}

Expand Down Expand Up @@ -622,7 +628,10 @@ static int handle_stdin_record(struct st_fcgi_generator_t *generator, struct st_
if (generator->resp.receiving->size == 0) {
size_t leftlen = header->contentLength - parse_result;
if (leftlen != 0) {
append_content(generator, input->bytes + FCGI_RECORD_HEADER_SIZE + parse_result, leftlen);
if (append_content(generator, input->bytes + FCGI_RECORD_HEADER_SIZE + parse_result, leftlen) != 0) {
h2o_req_log_error(generator->req, MODULE_NAME, "failed to allocate memory");
return -1;
}
}
} else {
h2o_buffer_consume(&generator->resp.receiving, parse_result);
Expand Down
5 changes: 5 additions & 0 deletions lib/handler/file.c
Original file line number Diff line number Diff line change
Expand Up @@ -425,6 +425,11 @@ static int send_dir_listing(h2o_req_t *req, const char *path, size_t path_len, i
body = build_dir_listing_html(&req->pool, req->path_normalized, dp);
closedir(dp);

if (body == NULL) {
h2o_send_error_503(req, "Service Unavailable", "please try again later", 0);
return 0;
}

bodyvec = h2o_iovec_init(body->bytes, body->size);
h2o_buffer_link_to_pool(body, &req->pool);

Expand Down
6 changes: 4 additions & 2 deletions lib/handler/file/templates.c.h
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,8 @@ static h2o_buffer_t *build_dir_listing_html(h2o_mem_pool_t *pool, h2o_iovec_t pa
h2o_iovec_t _s = (link_escaped);
if (_s.len != 0 && _s.base[_s.len - 1] == '\n')
--_s.len;
h2o_buffer_reserve(&_, _s.len);
if ((h2o_buffer_try_reserve(&_, _s.len)).base == NULL)
return NULL;
memcpy(_->bytes + _->size, _s.base, _s.len);
_->size += _s.len;
}
Expand All @@ -145,7 +146,8 @@ static h2o_buffer_t *build_dir_listing_html(h2o_mem_pool_t *pool, h2o_iovec_t pa
h2o_iovec_t _s = (label_escaped);
if (_s.len != 0 && _s.base[_s.len - 1] == '\n')
--_s.len;
h2o_buffer_reserve(&_, _s.len);
if ((h2o_buffer_try_reserve(&_, _s.len)).base == NULL)
return NULL;
memcpy(_->bytes + _->size, _s.base, _s.len);
_->size += _s.len;
}
Expand Down
5 changes: 4 additions & 1 deletion lib/handler/mruby/sender.c
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,10 @@ static mrb_value send_chunk_method(mrb_state *mrb, mrb_value self)
if (sender->super.bytes_left != SIZE_MAX && sender->super.bytes_left < len)
len = sender->super.bytes_left; /* trim data too long */
if (len != 0) {
h2o_buffer_reserve(&sender->receiving, len);
if ((h2o_buffer_try_reserve(&sender->receiving, len)).base == NULL) {
mrb_value exc = mrb_exc_new_str_lit(mrb, E_RUNTIME_ERROR, "failed to allocate memory");
mrb_exc_raise(mrb, exc);
}
memcpy(sender->receiving->bytes + sender->receiving->size, s, len);
sender->receiving->size += len;
if (!sender->super.final_sent && !sender->sending.inflight)
Expand Down
16 changes: 13 additions & 3 deletions lib/handler/status/requests.c
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,11 @@ static int collect_req_status(h2o_req_t *req, void *_cbdata)
--len; /* omit trailing LF */

/* append to buffer */
h2o_buffer_reserve(&cbdata->buffer, len + 3);
if ((h2o_buffer_try_reserve(&cbdata->buffer, len + 3)).base == NULL) {
if (logline != buf)
free(logline);
return -1;
}
memcpy(cbdata->buffer->bytes + cbdata->buffer->size, logline, len);
cbdata->buffer->size += len;

Expand All @@ -65,8 +69,14 @@ static void requests_status_per_thread(void *priv, h2o_context_t *ctx)
return;

h2o_buffer_init(&cbdata.buffer, &h2o_socket_buffer_prototype);
ctx->globalconf->http1.callbacks.foreach_request(ctx, collect_req_status, &cbdata);
ctx->globalconf->http2.callbacks.foreach_request(ctx, collect_req_status, &cbdata);
if (ctx->globalconf->http1.callbacks.foreach_request(ctx, collect_req_status, &cbdata) != 0) {
h2o_buffer_dispose(&cbdata.buffer);
return;
}
if (ctx->globalconf->http2.callbacks.foreach_request(ctx, collect_req_status, &cbdata) != 0) {
h2o_buffer_dispose(&cbdata.buffer);
return;
}

/* concat JSON elements */
if (cbdata.buffer->size != 0) {
Expand Down
2 changes: 1 addition & 1 deletion lib/http1.c
Original file line number Diff line number Diff line change
Expand Up @@ -458,7 +458,7 @@ static int write_req_non_streaming(void *_req, h2o_iovec_t payload, int is_end_e
{
struct st_h2o_http1_conn_t *conn = H2O_STRUCT_FROM_MEMBER(struct st_h2o_http1_conn_t, req, _req);

if (h2o_buffer_append(&conn->req._req_body.body, payload.base, payload.len) == 0)
if (h2o_buffer_try_append(&conn->req._req_body.body, payload.base, payload.len) == 0)
return -1;
conn->req.entity = h2o_iovec_init(conn->req._req_body.body->bytes, conn->req._req_body.body->size);

Expand Down
3 changes: 1 addition & 2 deletions lib/http2/connection.c
Original file line number Diff line number Diff line change
Expand Up @@ -648,7 +648,7 @@ static int write_req_non_streaming(void *_req, h2o_iovec_t payload, int is_end_s
{
h2o_http2_stream_t *stream = H2O_STRUCT_FROM_MEMBER(h2o_http2_stream_t, req, _req);

if (h2o_buffer_append(&stream->req._req_body.body, payload.base, payload.len) == 0)
if (h2o_buffer_try_append(&stream->req._req_body.body, payload.base, payload.len) == 0)
return -1;
proceed_request(&stream->req, payload.len, is_end_stream);

Expand All @@ -662,7 +662,6 @@ static int write_req_non_streaming(void *_req, h2o_iovec_t payload, int is_end_s
static int write_req_streaming_pre_dispatch(void *_req, h2o_iovec_t payload, int is_end_stream)
{
h2o_http2_stream_t *stream = H2O_STRUCT_FROM_MEMBER(h2o_http2_stream_t, req, _req);

if (h2o_buffer_append(&stream->req._req_body.body, payload.base, payload.len) == 0)
return -1;
stream->req.entity = h2o_iovec_init(stream->req._req_body.body->bytes, stream->req._req_body.body->size);
Expand Down