diff options
Diffstat (limited to 'src/http')
-rw-r--r-- | src/http/modules/ngx_http_range_filter_module.c | 13 | ||||
-rw-r--r-- | src/http/ngx_http_core_module.c | 4 | ||||
-rw-r--r-- | src/http/ngx_http_parse.c | 12 | ||||
-rw-r--r-- | src/http/ngx_http_request.c | 5 | ||||
-rw-r--r-- | src/http/ngx_http_spdy.c | 52 |
5 files changed, 77 insertions, 9 deletions
diff --git a/src/http/modules/ngx_http_range_filter_module.c b/src/http/modules/ngx_http_range_filter_module.c index 6a65e4849..bb9a42c54 100644 --- a/src/http/modules/ngx_http_range_filter_module.c +++ b/src/http/modules/ngx_http_range_filter_module.c @@ -274,7 +274,7 @@ ngx_http_range_parse(ngx_http_request_t *r, ngx_http_range_filter_ctx_t *ctx, ngx_uint_t ranges) { u_char *p; - off_t start, end, size, content_length; + off_t start, end, size, content_length, cutoff, cutlim; ngx_uint_t suffix; ngx_http_range_t *range; @@ -282,6 +282,9 @@ ngx_http_range_parse(ngx_http_request_t *r, ngx_http_range_filter_ctx_t *ctx, size = 0; content_length = r->headers_out.content_length_n; + cutoff = NGX_MAX_OFF_T_VALUE / 10; + cutlim = NGX_MAX_OFF_T_VALUE % 10; + for ( ;; ) { start = 0; end = 0; @@ -295,6 +298,10 @@ ngx_http_range_parse(ngx_http_request_t *r, ngx_http_range_filter_ctx_t *ctx, } while (*p >= '0' && *p <= '9') { + if (start >= cutoff && (start > cutoff || *p - '0' > cutlim)) { + return NGX_HTTP_RANGE_NOT_SATISFIABLE; + } + start = start * 10 + *p++ - '0'; } @@ -321,6 +328,10 @@ ngx_http_range_parse(ngx_http_request_t *r, ngx_http_range_filter_ctx_t *ctx, } while (*p >= '0' && *p <= '9') { + if (end >= cutoff && (end > cutoff || *p - '0' > cutlim)) { + return NGX_HTTP_RANGE_NOT_SATISFIABLE; + } + end = end * 10 + *p++ - '0'; } diff --git a/src/http/ngx_http_core_module.c b/src/http/ngx_http_core_module.c index 4484a5ed4..1bcd1045c 100644 --- a/src/http/ngx_http_core_module.c +++ b/src/http/ngx_http_core_module.c @@ -1935,6 +1935,10 @@ ngx_http_send_response(ngx_http_request_t *r, ngx_uint_t status, ngx_int_t ngx_http_send_header(ngx_http_request_t *r) { + if (r->post_action) { + return NGX_OK; + } + if (r->header_sent) { ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0, "header already sent"); diff --git a/src/http/ngx_http_parse.c b/src/http/ngx_http_parse.c index 02b4a0fd1..8d38a1920 100644 --- a/src/http/ngx_http_parse.c +++ b/src/http/ngx_http_parse.c @@ -2104,6 +2104,10 @@ ngx_http_parse_chunked(ngx_http_request_t *r, ngx_buf_t *b, goto invalid; case sw_chunk_size: + if (ctx->size > NGX_MAX_OFF_T_VALUE / 16) { + goto invalid; + } + if (ch >= '0' && ch <= '9') { ctx->size = ctx->size * 16 + (ch - '0'); break; @@ -2253,6 +2257,10 @@ data: ctx->state = state; b->pos = pos; + if (ctx->size > NGX_MAX_OFF_T_VALUE - 5) { + goto invalid; + } + switch (state) { case sw_chunk_start: @@ -2289,10 +2297,6 @@ data: } - if (ctx->size < 0 || ctx->length < 0) { - goto invalid; - } - return rc; done: diff --git a/src/http/ngx_http_request.c b/src/http/ngx_http_request.c index 845ada322..560c5f512 100644 --- a/src/http/ngx_http_request.c +++ b/src/http/ngx_http_request.c @@ -1227,12 +1227,11 @@ ngx_http_process_request_headers(ngx_event_t *rev) if (len > NGX_MAX_ERROR_STR - 300) { len = NGX_MAX_ERROR_STR - 300; - p[len++] = '.'; p[len++] = '.'; p[len++] = '.'; } ngx_log_error(NGX_LOG_INFO, c->log, 0, - "client sent too long header line: \"%*s\"", - len, r->header_name_start); + "client sent too long header line: \"%*s...\"", + len, r->header_name_start); ngx_http_finalize_request(r, NGX_HTTP_REQUEST_HEADER_TOO_LARGE); diff --git a/src/http/ngx_http_spdy.c b/src/http/ngx_http_spdy.c index 9bd624c82..bd6d73d82 100644 --- a/src/http/ngx_http_spdy.c +++ b/src/http/ngx_http_spdy.c @@ -3156,8 +3156,10 @@ ngx_http_spdy_close_stream_handler(ngx_event_t *ev) void ngx_http_spdy_close_stream(ngx_http_spdy_stream_t *stream, ngx_int_t rc) { + int tcp_nodelay; ngx_event_t *ev; - ngx_connection_t *fc; + ngx_connection_t *c, *fc; + ngx_http_core_loc_conf_t *clcf; ngx_http_spdy_stream_t **index, *s; ngx_http_spdy_srv_conf_t *sscf; ngx_http_spdy_connection_t *sc; @@ -3183,6 +3185,54 @@ ngx_http_spdy_close_stream(ngx_http_spdy_stream_t *stream, ngx_int_t rc) { sc->connection->error = 1; } + + } else { + c = sc->connection; + + if (c->tcp_nopush == NGX_TCP_NOPUSH_SET) { + if (ngx_tcp_push(c->fd) == -1) { + ngx_connection_error(c, ngx_socket_errno, + ngx_tcp_push_n " failed"); + c->error = 1; + tcp_nodelay = 0; + + } else { + c->tcp_nopush = NGX_TCP_NOPUSH_UNSET; + tcp_nodelay = ngx_tcp_nodelay_and_tcp_nopush ? 1 : 0; + } + + } else { + tcp_nodelay = 1; + } + + clcf = ngx_http_get_module_loc_conf(stream->request, + ngx_http_core_module); + + if (tcp_nodelay + && clcf->tcp_nodelay + && c->tcp_nodelay == NGX_TCP_NODELAY_UNSET) + { + ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "tcp_nodelay"); + + if (setsockopt(c->fd, IPPROTO_TCP, TCP_NODELAY, + (const void *) &tcp_nodelay, sizeof(int)) + == -1) + { +#if (NGX_SOLARIS) + /* Solaris returns EINVAL if a socket has been shut down */ + c->log_error = NGX_ERROR_IGNORE_EINVAL; +#endif + + ngx_connection_error(c, ngx_socket_errno, + "setsockopt(TCP_NODELAY) failed"); + + c->log_error = NGX_ERROR_INFO; + c->error = 1; + + } else { + c->tcp_nodelay = NGX_TCP_NODELAY_SET; + } + } } if (sc->stream == stream) { |