summaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authorSergey Kandaurov <pluknet@nginx.com>2021-07-15 16:28:21 +0300
committerSergey Kandaurov <pluknet@nginx.com>2021-07-15 16:28:21 +0300
commit161759443ccf0e800327af130a3c431789259fa4 (patch)
treebb51b1f5264ee1a44fb93e8c0341d1470cd5f97b /src
parent169b27a50b5e91184853bab96d9377b6f82d871c (diff)
parent7384cd1f315c51cd9e3b304ea3a68d160a9ee700 (diff)
downloadnginx-161759443ccf0e800327af130a3c431789259fa4.tar.gz
nginx-161759443ccf0e800327af130a3c431789259fa4.tar.bz2
Merged with the default branch.
Diffstat (limited to 'src')
-rw-r--r--src/core/nginx.h4
-rw-r--r--src/core/ngx_connection.c25
-rw-r--r--src/core/ngx_rbtree.h3
-rw-r--r--src/core/ngx_resolver.c4
-rw-r--r--src/core/ngx_string.c45
-rw-r--r--src/event/ngx_event.c23
-rw-r--r--src/event/ngx_event_openssl.c47
-rw-r--r--src/event/ngx_event_openssl.h1
-rw-r--r--src/event/ngx_event_timer.c4
-rw-r--r--src/http/modules/ngx_http_fastcgi_module.c8
-rw-r--r--src/http/modules/ngx_http_grpc_module.c15
-rw-r--r--src/http/modules/ngx_http_proxy_module.c12
-rw-r--r--src/http/modules/ngx_http_scgi_module.c8
-rw-r--r--src/http/modules/ngx_http_uwsgi_module.c8
-rw-r--r--src/http/ngx_http_parse.c118
-rw-r--r--src/http/ngx_http_request.c47
-rw-r--r--src/http/ngx_http_request.h36
-rw-r--r--src/http/v2/ngx_http_v2.c5
-rw-r--r--src/os/unix/ngx_readv_chain.c2
-rw-r--r--src/os/win32/ngx_win32_init.c6
-rw-r--r--src/os/win32/ngx_wsarecv_chain.c6
-rw-r--r--src/os/win32/ngx_wsasend_chain.c26
22 files changed, 247 insertions, 206 deletions
diff --git a/src/core/nginx.h b/src/core/nginx.h
index d8c8289a8..c4cab7b7c 100644
--- a/src/core/nginx.h
+++ b/src/core/nginx.h
@@ -9,8 +9,8 @@
#define _NGINX_H_INCLUDED_
-#define nginx_version 1021000
-#define NGINX_VERSION "1.21.0"
+#define nginx_version 1021001
+#define NGINX_VERSION "1.21.1"
#define NGINX_VER "nginx/" NGINX_VERSION
#ifdef NGX_BUILD
diff --git a/src/core/ngx_connection.c b/src/core/ngx_connection.c
index 2c0346f6b..974f48c9a 100644
--- a/src/core/ngx_connection.c
+++ b/src/core/ngx_connection.c
@@ -495,21 +495,24 @@ ngx_open_listening_sockets(ngx_cycle_t *cycle)
return NGX_ERROR;
}
- if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR,
- (const void *) &reuseaddr, sizeof(int))
- == -1)
- {
- ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno,
- "setsockopt(SO_REUSEADDR) %V failed",
- &ls[i].addr_text);
+ if (ls[i].type != SOCK_DGRAM || !ngx_test_config) {
- if (ngx_close_socket(s) == -1) {
+ if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR,
+ (const void *) &reuseaddr, sizeof(int))
+ == -1)
+ {
ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno,
- ngx_close_socket_n " %V failed",
+ "setsockopt(SO_REUSEADDR) %V failed",
&ls[i].addr_text);
- }
- return NGX_ERROR;
+ if (ngx_close_socket(s) == -1) {
+ ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno,
+ ngx_close_socket_n " %V failed",
+ &ls[i].addr_text);
+ }
+
+ return NGX_ERROR;
+ }
}
#if (NGX_HAVE_REUSEPORT)
diff --git a/src/core/ngx_rbtree.h b/src/core/ngx_rbtree.h
index 97f0e3e11..e8c358213 100644
--- a/src/core/ngx_rbtree.h
+++ b/src/core/ngx_rbtree.h
@@ -47,6 +47,9 @@ struct ngx_rbtree_s {
(tree)->sentinel = s; \
(tree)->insert = i
+#define ngx_rbtree_data(node, type, link) \
+ (type *) ((u_char *) (node) - offsetof(type, link))
+
void ngx_rbtree_insert(ngx_rbtree_t *tree, ngx_rbtree_node_t *node);
void ngx_rbtree_delete(ngx_rbtree_t *tree, ngx_rbtree_node_t *node);
diff --git a/src/core/ngx_resolver.c b/src/core/ngx_resolver.c
index 58d5f3ec4..6d129e56a 100644
--- a/src/core/ngx_resolver.c
+++ b/src/core/ngx_resolver.c
@@ -51,9 +51,7 @@ typedef struct {
} ngx_resolver_an_t;
-#define ngx_resolver_node(n) \
- (ngx_resolver_node_t *) \
- ((u_char *) (n) - offsetof(ngx_resolver_node_t, node))
+#define ngx_resolver_node(n) ngx_rbtree_data(n, ngx_resolver_node_t, node)
static ngx_int_t ngx_udp_connect(ngx_resolver_connection_t *rec);
diff --git a/src/core/ngx_string.c b/src/core/ngx_string.c
index 5cc9b26f9..98f270aca 100644
--- a/src/core/ngx_string.c
+++ b/src/core/ngx_string.c
@@ -1493,19 +1493,32 @@ ngx_escape_uri(u_char *dst, u_char *src, size_t size, ngx_uint_t type)
uint32_t *escape;
static u_char hex[] = "0123456789ABCDEF";
- /* " ", "#", "%", "?", %00-%1F, %7F-%FF */
+ /*
+ * Per RFC 3986 only the following chars are allowed in URIs unescaped:
+ *
+ * unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~"
+ * gen-delims = ":" / "/" / "?" / "#" / "[" / "]" / "@"
+ * sub-delims = "!" / "$" / "&" / "'" / "(" / ")"
+ * / "*" / "+" / "," / ";" / "="
+ *
+ * And "%" can appear as a part of escaping itself. The following
+ * characters are not allowed and need to be escaped: %00-%1F, %7F-%FF,
+ * " ", """, "<", ">", "\", "^", "`", "{", "|", "}".
+ */
+
+ /* " ", "#", "%", "?", not allowed */
static uint32_t uri[] = {
0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */
/* ?>=< ;:98 7654 3210 /.-, +*)( '&%$ #"! */
- 0x80000029, /* 1000 0000 0000 0000 0000 0000 0010 1001 */
+ 0xd000002d, /* 1101 0000 0000 0000 0000 0000 0010 1101 */
/* _^]\ [ZYX WVUT SRQP ONML KJIH GFED CBA@ */
- 0x00000000, /* 0000 0000 0000 0000 0000 0000 0000 0000 */
+ 0x50000000, /* 0101 0000 0000 0000 0000 0000 0000 0000 */
/* ~}| {zyx wvut srqp onml kjih gfed cba` */
- 0x80000000, /* 1000 0000 0000 0000 0000 0000 0000 0000 */
+ 0xb8000001, /* 1011 1000 0000 0000 0000 0000 0000 0001 */
0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */
0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */
@@ -1513,19 +1526,19 @@ ngx_escape_uri(u_char *dst, u_char *src, size_t size, ngx_uint_t type)
0xffffffff /* 1111 1111 1111 1111 1111 1111 1111 1111 */
};
- /* " ", "#", "%", "&", "+", "?", %00-%1F, %7F-%FF */
+ /* " ", "#", "%", "&", "+", ";", "?", not allowed */
static uint32_t args[] = {
0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */
/* ?>=< ;:98 7654 3210 /.-, +*)( '&%$ #"! */
- 0x88000869, /* 1000 1000 0000 0000 0000 1000 0110 1001 */
+ 0xd800086d, /* 1101 1000 0000 0000 0000 1000 0110 1101 */
/* _^]\ [ZYX WVUT SRQP ONML KJIH GFED CBA@ */
- 0x00000000, /* 0000 0000 0000 0000 0000 0000 0000 0000 */
+ 0x50000000, /* 0101 0000 0000 0000 0000 0000 0000 0000 */
/* ~}| {zyx wvut srqp onml kjih gfed cba` */
- 0x80000000, /* 1000 0000 0000 0000 0000 0000 0000 0000 */
+ 0xb8000001, /* 1011 1000 0000 0000 0000 0000 0000 0001 */
0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */
0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */
@@ -1553,19 +1566,19 @@ ngx_escape_uri(u_char *dst, u_char *src, size_t size, ngx_uint_t type)
0xffffffff /* 1111 1111 1111 1111 1111 1111 1111 1111 */
};
- /* " ", "#", """, "%", "'", %00-%1F, %7F-%FF */
+ /* " ", "#", """, "%", "'", not allowed */
static uint32_t html[] = {
0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */
/* ?>=< ;:98 7654 3210 /.-, +*)( '&%$ #"! */
- 0x000000ad, /* 0000 0000 0000 0000 0000 0000 1010 1101 */
+ 0x500000ad, /* 0101 0000 0000 0000 0000 0000 1010 1101 */
/* _^]\ [ZYX WVUT SRQP ONML KJIH GFED CBA@ */
- 0x00000000, /* 0000 0000 0000 0000 0000 0000 0000 0000 */
+ 0x50000000, /* 0101 0000 0000 0000 0000 0000 0000 0000 */
/* ~}| {zyx wvut srqp onml kjih gfed cba` */
- 0x80000000, /* 1000 0000 0000 0000 0000 0000 0000 0000 */
+ 0xb8000001, /* 1011 1000 0000 0000 0000 0000 0000 0001 */
0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */
0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */
@@ -1573,19 +1586,19 @@ ngx_escape_uri(u_char *dst, u_char *src, size_t size, ngx_uint_t type)
0xffffffff /* 1111 1111 1111 1111 1111 1111 1111 1111 */
};
- /* " ", """, "'", %00-%1F, %7F-%FF */
+ /* " ", """, "'", not allowed */
static uint32_t refresh[] = {
0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */
/* ?>=< ;:98 7654 3210 /.-, +*)( '&%$ #"! */
- 0x00000085, /* 0000 0000 0000 0000 0000 0000 1000 0101 */
+ 0x50000085, /* 0101 0000 0000 0000 0000 0000 1000 0101 */
/* _^]\ [ZYX WVUT SRQP ONML KJIH GFED CBA@ */
- 0x00000000, /* 0000 0000 0000 0000 0000 0000 0000 0000 */
+ 0x50000000, /* 0101 0000 0000 0000 0000 0000 0000 0000 */
/* ~}| {zyx wvut srqp onml kjih gfed cba` */
- 0x80000000, /* 1000 0000 0000 0000 0000 0000 0000 0000 */
+ 0xd8000001, /* 1011 1000 0000 0000 0000 0000 0000 0001 */
0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */
0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */
diff --git a/src/event/ngx_event.c b/src/event/ngx_event.c
index a59a4c9b5..d61eda25e 100644
--- a/src/event/ngx_event.c
+++ b/src/event/ngx_event.c
@@ -477,20 +477,23 @@ ngx_event_init_conf(ngx_cycle_t *cycle, void *conf)
#if (NGX_HAVE_REUSEPORT)
- ls = cycle->listening.elts;
- for (i = 0; i < cycle->listening.nelts; i++) {
+ if (!ngx_test_config) {
- if (!ls[i].reuseport || ls[i].worker != 0) {
- continue;
- }
+ ls = cycle->listening.elts;
+ for (i = 0; i < cycle->listening.nelts; i++) {
- if (ngx_clone_listening(cycle, &ls[i]) != NGX_OK) {
- return NGX_CONF_ERROR;
- }
+ if (!ls[i].reuseport || ls[i].worker != 0) {
+ continue;
+ }
- /* cloning may change cycle->listening.elts */
+ if (ngx_clone_listening(cycle, &ls[i]) != NGX_OK) {
+ return NGX_CONF_ERROR;
+ }
- ls = cycle->listening.elts;
+ /* cloning may change cycle->listening.elts */
+
+ ls = cycle->listening.elts;
+ }
}
#endif
diff --git a/src/event/ngx_event_openssl.c b/src/event/ngx_event_openssl.c
index 50a9d8ad1..e982c187d 100644
--- a/src/event/ngx_event_openssl.c
+++ b/src/event/ngx_event_openssl.c
@@ -2896,6 +2896,7 @@ ngx_int_t
ngx_ssl_shutdown(ngx_connection_t *c)
{
int n, sslerr, mode;
+ ngx_int_t rc;
ngx_err_t err;
ngx_uint_t tries;
@@ -2906,6 +2907,8 @@ ngx_ssl_shutdown(ngx_connection_t *c)
}
#endif
+ rc = NGX_OK;
+
ngx_ssl_ocsp_cleanup(c);
if (SSL_in_init(c->ssl->connection)) {
@@ -2915,11 +2918,7 @@ ngx_ssl_shutdown(ngx_connection_t *c)
* Avoid calling SSL_shutdown() if handshake wasn't completed.
*/
- SSL_free(c->ssl->connection);
- c->ssl = NULL;
- c->recv = ngx_recv;
-
- return NGX_OK;
+ goto done;
}
if (c->timedout || c->error || c->buffered) {
@@ -2961,11 +2960,7 @@ ngx_ssl_shutdown(ngx_connection_t *c)
ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL_shutdown: %d", n);
if (n == 1) {
- SSL_free(c->ssl->connection);
- c->ssl = NULL;
- c->recv = ngx_recv;
-
- return NGX_OK;
+ goto done;
}
if (n == 0 && tries-- > 1) {
@@ -2991,11 +2986,11 @@ ngx_ssl_shutdown(ngx_connection_t *c)
}
if (ngx_handle_read_event(c->read, 0) != NGX_OK) {
- return NGX_ERROR;
+ goto failed;
}
if (ngx_handle_write_event(c->write, 0) != NGX_OK) {
- return NGX_ERROR;
+ goto failed;
}
ngx_add_timer(c->read, 3000);
@@ -3004,23 +2999,33 @@ ngx_ssl_shutdown(ngx_connection_t *c)
}
if (sslerr == SSL_ERROR_ZERO_RETURN || ERR_peek_error() == 0) {
- SSL_free(c->ssl->connection);
- c->ssl = NULL;
- c->recv = ngx_recv;
-
- return NGX_OK;
+ goto done;
}
err = (sslerr == SSL_ERROR_SYSCALL) ? ngx_errno : 0;
ngx_ssl_connection_error(c, sslerr, err, "SSL_shutdown() failed");
- SSL_free(c->ssl->connection);
- c->ssl = NULL;
- c->recv = ngx_recv;
+ break;
+ }
- return NGX_ERROR;
+failed:
+
+ rc = NGX_ERROR;
+
+done:
+
+ if (c->ssl->shutdown_without_free) {
+ c->ssl->shutdown_without_free = 0;
+ c->recv = ngx_recv;
+ return rc;
}
+
+ SSL_free(c->ssl->connection);
+ c->ssl = NULL;
+ c->recv = ngx_recv;
+
+ return rc;
}
diff --git a/src/event/ngx_event_openssl.h b/src/event/ngx_event_openssl.h
index cb9aceb58..8e365545e 100644
--- a/src/event/ngx_event_openssl.h
+++ b/src/event/ngx_event_openssl.h
@@ -108,6 +108,7 @@ struct ngx_ssl_connection_s {
unsigned buffer:1;
unsigned no_wait_shutdown:1;
unsigned no_send_shutdown:1;
+ unsigned shutdown_without_free:1;
unsigned handshake_buffer_set:1;
unsigned try_early_data:1;
unsigned in_early:1;
diff --git a/src/event/ngx_event_timer.c b/src/event/ngx_event_timer.c
index 698b88fae..35052bc29 100644
--- a/src/event/ngx_event_timer.c
+++ b/src/event/ngx_event_timer.c
@@ -73,7 +73,7 @@ ngx_event_expire_timers(void)
return;
}
- ev = (ngx_event_t *) ((char *) node - offsetof(ngx_event_t, timer));
+ ev = ngx_rbtree_data(node, ngx_event_t, timer);
ngx_log_debug2(NGX_LOG_DEBUG_EVENT, ev->log, 0,
"event timer del: %d: %M",
@@ -113,7 +113,7 @@ ngx_event_no_timers_left(void)
node;
node = ngx_rbtree_next(&ngx_event_timer_rbtree, node))
{
- ev = (ngx_event_t *) ((char *) node - offsetof(ngx_event_t, timer));
+ ev = ngx_rbtree_data(node, ngx_event_t, timer);
if (!ev->cancelable) {
return NGX_AGAIN;
diff --git a/src/http/modules/ngx_http_fastcgi_module.c b/src/http/modules/ngx_http_fastcgi_module.c
index 5191880e3..69ac0f72c 100644
--- a/src/http/modules/ngx_http_fastcgi_module.c
+++ b/src/http/modules/ngx_http_fastcgi_module.c
@@ -2019,10 +2019,12 @@ ngx_http_fastcgi_process_header(ngx_http_request_t *r)
break;
}
- /* there was error while a header line parsing */
+ /* rc == NGX_HTTP_PARSE_INVALID_HEADER */
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "upstream sent invalid header");
+ ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
+ "upstream sent invalid header: \"%*s\\x%02xd...\"",
+ r->header_end - r->header_name_start,
+ r->header_name_start, *r->header_end);
return NGX_HTTP_UPSTREAM_INVALID_HEADER;
}
diff --git a/src/http/modules/ngx_http_grpc_module.c b/src/http/modules/ngx_http_grpc_module.c
index 2e20e5ffd..65bd1e6c3 100644
--- a/src/http/modules/ngx_http_grpc_module.c
+++ b/src/http/modules/ngx_http_grpc_module.c
@@ -121,6 +121,7 @@ typedef struct {
unsigned done:1;
unsigned status:1;
unsigned rst:1;
+ unsigned goaway:1;
ngx_http_request_t *request;
@@ -1210,6 +1211,7 @@ ngx_http_grpc_reinit_request(ngx_http_request_t *r)
ctx->done = 0;
ctx->status = 0;
ctx->rst = 0;
+ ctx->goaway = 0;
ctx->connection = NULL;
return NGX_OK;
@@ -1565,6 +1567,7 @@ ngx_http_grpc_body_output_filter(void *data, ngx_chain_t *in)
&& ctx->out == NULL
&& ctx->output_closed
&& !ctx->output_blocked
+ && !ctx->goaway
&& ctx->state == ngx_http_grpc_st_start)
{
u->keepalive = 1;
@@ -1714,6 +1717,8 @@ ngx_http_grpc_process_header(ngx_http_request_t *r)
return NGX_HTTP_UPSTREAM_INVALID_HEADER;
}
+ ctx->goaway = 1;
+
continue;
}
@@ -1907,6 +1912,7 @@ ngx_http_grpc_process_header(ngx_http_request_t *r)
&& ctx->out == NULL
&& ctx->output_closed
&& !ctx->output_blocked
+ && !ctx->goaway
&& b->last == b->pos)
{
u->keepalive = 1;
@@ -2035,6 +2041,7 @@ ngx_http_grpc_filter(void *data, ssize_t bytes)
if (ctx->in == NULL
&& ctx->output_closed
&& !ctx->output_blocked
+ && !ctx->goaway
&& ctx->state == ngx_http_grpc_st_start)
{
u->keepalive = 1;
@@ -2170,6 +2177,8 @@ ngx_http_grpc_filter(void *data, ssize_t bytes)
}
ctx->rst = 1;
+
+ continue;
}
if (ctx->type == NGX_HTTP_V2_GOAWAY_FRAME) {
@@ -2204,6 +2213,8 @@ ngx_http_grpc_filter(void *data, ssize_t bytes)
return NGX_ERROR;
}
+ ctx->goaway = 1;
+
continue;
}
@@ -3373,7 +3384,7 @@ ngx_http_grpc_validate_header_name(ngx_http_request_t *r, ngx_str_t *s)
return NGX_ERROR;
}
- if (ch == '\0' || ch == CR || ch == LF) {
+ if (ch <= 0x20 || ch == 0x7f) {
return NGX_ERROR;
}
}
@@ -3475,6 +3486,8 @@ ngx_http_grpc_parse_rst_stream(ngx_http_request_t *r, ngx_http_grpc_ctx_t *ctx,
return NGX_AGAIN;
}
+ ctx->state = ngx_http_grpc_st_start;
+
return NGX_OK;
}
diff --git a/src/http/modules/ngx_http_proxy_module.c b/src/http/modules/ngx_http_proxy_module.c
index 64190f1a0..368297e77 100644
--- a/src/http/modules/ngx_http_proxy_module.c
+++ b/src/http/modules/ngx_http_proxy_module.c
@@ -1186,7 +1186,7 @@ ngx_http_proxy_create_key(ngx_http_request_t *r)
loc_len = (r->valid_location && ctx->vars.uri.len) ? plcf->location.len : 0;
- if (r->quoted_uri || r->space_in_uri || r->internal) {
+ if (r->quoted_uri || r->internal) {
escape = 2 * ngx_escape_uri(NULL, r->uri.data + loc_len,
r->uri.len - loc_len, NGX_ESCAPE_URI);
} else {
@@ -1299,7 +1299,7 @@ ngx_http_proxy_create_request(ngx_http_request_t *r)
loc_len = (r->valid_location && ctx->vars.uri.len) ?
plcf->location.len : 0;
- if (r->quoted_uri || r->space_in_uri || r->internal) {
+ if (r->quoted_uri || r->internal) {
escape = 2 * ngx_escape_uri(NULL, r->uri.data + loc_len,
r->uri.len - loc_len, NGX_ESCAPE_URI);
}
@@ -2019,10 +2019,12 @@ ngx_http_proxy_process_header(ngx_http_request_t *r)
return NGX_AGAIN;
}
- /* there was error while a header line parsing */
+ /* rc == NGX_HTTP_PARSE_INVALID_HEADER */
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "upstream sent invalid header");
+ ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
+ "upstream sent invalid header: \"%*s\\x%02xd...\"",
+ r->header_end - r->header_name_start,
+ r->header_name_start, *r->header_end);
return NGX_HTTP_UPSTREAM_INVALID_HEADER;
}
diff --git a/src/http/modules/ngx_http_scgi_module.c b/src/http/modules/ngx_http_scgi_module.c
index 600999c88..570713df9 100644
--- a/src/http/modules/ngx_http_scgi_module.c
+++ b/src/http/modules/ngx_http_scgi_module.c
@@ -1140,10 +1140,12 @@ ngx_http_scgi_process_header(ngx_http_request_t *r)
return NGX_AGAIN;
}
- /* there was error while a header line parsing */
+ /* rc == NGX_HTTP_PARSE_INVALID_HEADER */
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "upstream sent invalid header");
+ ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
+ "upstream sent invalid header: \"%*s\\x%02xd...\"",
+ r->header_end - r->header_name_start,
+ r->header_name_start, *r->header_end);
return NGX_HTTP_UPSTREAM_INVALID_HEADER;
}
diff --git a/src/http/modules/ngx_http_uwsgi_module.c b/src/http/modules/ngx_http_uwsgi_module.c
index 655be98c7..40a06c78e 100644
--- a/src/http/modules/ngx_http_uwsgi_module.c
+++ b/src/http/modules/ngx_http_uwsgi_module.c
@@ -1361,10 +1361,12 @@ ngx_http_uwsgi_process_header(ngx_http_request_t *r)
return NGX_AGAIN;
}
- /* there was error while a header line parsing */
+ /* rc == NGX_HTTP_PARSE_INVALID_HEADER */
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "upstream sent invalid header");
+ ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
+ "upstream sent invalid header: \"%*s\\x%02xd...\"",
+ r->header_end - r->header_name_start,
+ r->header_name_start, *r->header_end);
return NGX_HTTP_UPSTREAM_INVALID_HEADER;
}
diff --git a/src/http/ngx_http_parse.c b/src/http/ngx_http_parse.c
index 20ad89a77..6460da293 100644
--- a/src/http/ngx_http_parse.c
+++ b/src/http/ngx_http_parse.c
@@ -11,7 +11,7 @@
static uint32_t usual[] = {
- 0xffffdbfe, /* 1111 1111 1111 1111 1101 1011 1111 1110 */
+ 0x00000000, /* 0000 0000 0000 0000 0000 0000 0000 0000 */
/* ?>=< ;:98 7654 3210 /.-, +*)( '&%$ #"! */
0x7fff37d6, /* 0111 1111 1111 1111 0011 0111 1101 0110 */
@@ -24,7 +24,7 @@ static uint32_t usual[] = {
#endif
/* ~}| {zyx wvut srqp onml kjih gfed cba` */
- 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */
+ 0x7fffffff, /* 0111 1111 1111 1111 1111 1111 1111 1111 */
0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */
0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */
@@ -116,10 +116,8 @@ ngx_http_parse_request_line(ngx_http_request_t *r, ngx_buf_t *b)
sw_host_end,
sw_host_ip_literal,
sw_port,
- sw_host_http_09,
sw_after_slash_in_uri,
sw_check_uri,
- sw_check_uri_http_09,
sw_uri,
sw_http_09,
sw_http_H,
@@ -246,6 +244,11 @@ ngx_http_parse_request_line(ngx_http_request_t *r, ngx_buf_t *b)
r->method = NGX_HTTP_OPTIONS;
}
+ if (ngx_str7_cmp(m, 'C', 'O', 'N', 'N', 'E', 'C', 'T', ' '))
+ {
+ r->method = NGX_HTTP_CONNECT;
+ }
+
break;
case 8:
@@ -393,7 +396,7 @@ ngx_http_parse_request_line(ngx_http_request_t *r, ngx_buf_t *b)
*/
r->uri_start = r->schema_end + 1;
r->uri_end = r->schema_end + 2;
- state = sw_host_http_09;
+ state = sw_http_09;
break;
default:
return NGX_HTTP_PARSE_INVALID_REQUEST;
@@ -467,35 +470,13 @@ ngx_http_parse_request_line(ngx_http_request_t *r, ngx_buf_t *b)
*/
r->uri_start = r->schema_end + 1;
r->uri_end = r->schema_end + 2;
- state = sw_host_http_09;
- break;
- default:
- return NGX_HTTP_PARSE_INVALID_REQUEST;
- }
- break;
-
- /* space+ after "http://host[:port] " */
- case sw_host_http_09:
- switch (ch) {
- case ' ':
- break;
- case CR:
- r->http_minor = 9;
- state = sw_almost_done;
- break;
- case LF:
- r->http_minor = 9;
- goto done;
- case 'H':
- r->http_protocol.data = p;
- state = sw_http_H;
+ state = sw_http_09;
break;
default:
return NGX_HTTP_PARSE_INVALID_REQUEST;
}
break;
-
/* check "/.", "//", "%", and "\" (Win32) in URI */
case sw_after_slash_in_uri:
@@ -507,7 +488,7 @@ ngx_http_parse_request_line(ngx_http_request_t *r, ngx_buf_t *b)
switch (ch) {
case ' ':
r->uri_end = p;
- state = sw_check_uri_http_09;
+ state = sw_http_09;
break;
case CR:
r->uri_end = p;
@@ -547,9 +528,10 @@ ngx_http_parse_request_line(ngx_http_request_t *r, ngx_buf_t *b)
case '+':
r->plus_in_uri = 1;
break;
- case '\0':
- return NGX_HTTP_PARSE_INVALID_REQUEST;
default:
+ if (ch < 0x20 || ch == 0x7f) {
+ return NGX_HTTP_PARSE_INVALID_REQUEST;
+ }
state = sw_check_uri;
break;
}
@@ -579,7 +561,7 @@ ngx_http_parse_request_line(ngx_http_request_t *r, ngx_buf_t *b)
break;
case ' ':
r->uri_end = p;
- state = sw_check_uri_http_09;
+ state = sw_http_09;
break;
case CR:
r->uri_end = p;
@@ -611,36 +593,14 @@ ngx_http_parse_request_line(ngx_http_request_t *r, ngx_buf_t *b)
case '+':
r->plus_in_uri = 1;
break;
- case '\0':
- return NGX_HTTP_PARSE_INVALID_REQUEST;
- }
- break;
-
- /* space+ after URI */
- case sw_check_uri_http_09:
- switch (ch) {
- case ' ':
- break;
- case CR:
- r->http_minor = 9;
- state = sw_almost_done;
- break;
- case LF:
- r->http_minor = 9;
- goto done;
- case 'H':
- r->http_protocol.data = p;
- state = sw_http_H;
- break;
default:
- r->space_in_uri = 1;
- state = sw_check_uri;
- p--;
+ if (ch < 0x20 || ch == 0x7f) {
+ return NGX_HTTP_PARSE_INVALID_REQUEST;
+ }
break;
}
break;
-
/* URI */
case sw_uri:
@@ -665,8 +625,11 @@ ngx_http_parse_request_line(ngx_http_request_t *r, ngx_buf_t *b)
case '#':
r->complex_uri = 1;
break;
- case '\0':
- return NGX_HTTP_PARSE_INVALID_REQUEST;
+ default:
+ if (ch < 0x20 || ch == 0x7f) {
+ return NGX_HTTP_PARSE_INVALID_REQUEST;
+ }
+ break;
}
break;
@@ -687,10 +650,7 @@ ngx_http_parse_request_line(ngx_http_request_t *r, ngx_buf_t *b)
state = sw_http_H;
break;
default:
- r->space_in_uri = 1;
- state = sw_uri;
- p--;
- break;
+ return NGX_HTTP_PARSE_INVALID_REQUEST;
}
break;
@@ -933,7 +893,8 @@ ngx_http_parse_header_line(ngx_http_request_t *r, ngx_buf_t *b,
break;
}
- if (ch == '\0') {
+ if (ch <= 0x20 || ch == 0x7f || ch == ':') {
+ r->header_end = p;
return NGX_HTTP_PARSE_INVALID_HEADER;
}
@@ -1001,7 +962,8 @@ ngx_http_parse_header_line(ngx_http_request_t *r, ngx_buf_t *b,
break;
}
- if (ch == '\0') {
+ if (ch <= 0x20 || ch == 0x7f) {
+ r->header_end = p;
return NGX_HTTP_PARSE_INVALID_HEADER;
}
@@ -1024,6 +986,7 @@ ngx_http_parse_header_line(ngx_http_request_t *r, ngx_buf_t *b,
r->header_end = p;
goto done;
case '\0':
+ r->header_end = p;
return NGX_HTTP_PARSE_INVALID_HEADER;
default:
r->header_start = p;
@@ -1047,6 +1010,7 @@ ngx_http_parse_header_line(ngx_http_request_t *r, ngx_buf_t *b,
r->header_end = p;
goto done;
case '\0':
+ r->header_end = p;
return NGX_HTTP_PARSE_INVALID_HEADER;
}
break;
@@ -1062,6 +1026,7 @@ ngx_http_parse_header_line(ngx_http_request_t *r, ngx_buf_t *b,
case LF:
goto done;
case '\0':
+ r->header_end = p;
return NGX_HTTP_PARSE_INVALID_HEADER;
default:
state = sw_value;
@@ -1165,10 +1130,6 @@ ngx_http_parse_uri(ngx_http_request_t *r)
}
switch (ch) {
- case ' ':
- r->space_in_uri = 1;
- state = sw_check_uri;
- break;
case '.':
r->complex_uri = 1;
state = sw_uri;
@@ -1199,6 +1160,9 @@ ngx_http_parse_uri(ngx_http_request_t *r)
r->plus_in_uri = 1;
break;
default:
+ if (ch <= 0x20 || ch == 0x7f) {
+ return NGX_ERROR;
+ }
state = sw_check_uri;
break;
}
@@ -1226,9 +1190,6 @@ ngx_http_parse_uri(ngx_http_request_t *r)
case '.':
r->uri_ext = p + 1;
break;
- case ' ':
- r->space_in_uri = 1;
- break;
#if (NGX_WIN32)
case '\\':
r->complex_uri = 1;
@@ -1250,6 +1211,11 @@ ngx_http_parse_uri(ngx_http_request_t *r)
case '+':
r->plus_in_uri = 1;
break;
+ default:
+ if (ch <= 0x20 || ch == 0x7f) {
+ return NGX_ERROR;
+ }
+ break;
}
break;
@@ -1261,12 +1227,14 @@ ngx_http_parse_uri(ngx_http_request_t *r)
}
switch (ch) {
- case ' ':
- r->space_in_uri = 1;
- break;
case '#':
r->complex_uri = 1;
break;
+ default:
+ if (ch <= 0x20 || ch == 0x7f) {
+ return NGX_ERROR;
+ }
+ break;
}
break;
}
diff --git a/src/http/ngx_http_request.c b/src/http/ngx_http_request.c
index 1816c0360..a27d29368 100644
--- a/src/http/ngx_http_request.c
+++ b/src/http/ngx_http_request.c
@@ -1273,7 +1273,7 @@ ngx_http_process_request_uri(ngx_http_request_t *r)
r->unparsed_uri.len = r->uri_end - r->uri_start;
r->unparsed_uri.data = r->uri_start;
- r->valid_unparsed_uri = (r->space_in_uri || r->empty_path_in_uri) ? 0 : 1;
+ r->valid_unparsed_uri = r->empty_path_in_uri ? 0 : 1;
if (r->uri_ext) {
if (r->args_start) {
@@ -1531,7 +1531,9 @@ ngx_http_process_request_headers(ngx_event_t *rev)
/* rc == NGX_HTTP_PARSE_INVALID_HEADER */
ngx_log_error(NGX_LOG_INFO, c->log, 0,
- "client sent invalid header line");
+ "client sent invalid header line: \"%*s\\x%02xd...\"",
+ r->header_end - r->header_name_start,
+ r->header_name_start, *r->header_end);
ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
break;
@@ -1989,20 +1991,20 @@ ngx_http_process_request_header(ngx_http_request_t *r)
}
}
- if (r->method == NGX_HTTP_TRACE) {
- ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
- "client sent TRACE method");
- ngx_http_finalize_request(r, NGX_HTTP_NOT_ALLOWED);
- return NGX_ERROR;
- }
-
if (r->headers_in.transfer_encoding) {
if (r->headers_in.transfer_encoding->value.len == 7
&& ngx_strncasecmp(r->headers_in.transfer_encoding->value.data,
(u_char *) "chunked", 7) == 0)
{
- r->headers_in.content_length = NULL;
- r->headers_in.content_length_n = -1;
+ if (r->headers_in.content_length) {
+ ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
+ "client sent \"Content-Length\" and "
+ "\"Transfer-Encoding\" headers "
+ "at the same time");
+ ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
+ return NGX_ERROR;
+ }
+
r->headers_in.chunked = 1;
} else {
@@ -2022,6 +2024,20 @@ ngx_http_process_request_header(ngx_http_request_t *r)
}
}
+ if (r->method == NGX_HTTP_CONNECT) {
+ ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
+ "client sent CONNECT method");
+ ngx_http_finalize_request(r, NGX_HTTP_NOT_ALLOWED);
+ return NGX_ERROR;
+ }
+
+ if (r->method == NGX_HTTP_TRACE) {
+ ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
+ "client sent TRACE method");
+ ngx_http_finalize_request(r, NGX_HTTP_NOT_ALLOWED);
+ return NGX_ERROR;
+ }
+
return NGX_OK;
}
@@ -2169,15 +2185,16 @@ ngx_http_validate_host(ngx_str_t *host, ngx_pool_t *pool, ngx_uint_t alloc)
}
break;
- case '\0':
- return NGX_DECLINED;
-
default:
if (ngx_path_separator(ch)) {
return NGX_DECLINED;
}
+ if (ch <= 0x20 || ch == 0x7f) {
+ return NGX_DECLINED;
+ }
+
if (ch >= 'A' && ch <= 'Z') {
alloc = 1;
}
@@ -3429,6 +3446,8 @@ ngx_http_set_lingering_close(ngx_connection_t *c)
if (c->ssl) {
ngx_int_t rc;
+ c->ssl->shutdown_without_free = 1;
+
rc = ngx_ssl_shutdown(c);
if (rc == NGX_ERROR) {
diff --git a/src/http/ngx_http_request.h b/src/http/ngx_http_request.h
index 60ef4fec1..cd6bd6618 100644
--- a/src/http/ngx_http_request.h
+++ b/src/http/ngx_http_request.h
@@ -26,22 +26,23 @@
#define NGX_HTTP_VERSION_20 2000
#define NGX_HTTP_VERSION_30 3000
-#define NGX_HTTP_UNKNOWN 0x0001
-#define NGX_HTTP_GET 0x0002
-#define NGX_HTTP_HEAD 0x0004
-#define NGX_HTTP_POST 0x0008
-#define NGX_HTTP_PUT 0x0010
-#define NGX_HTTP_DELETE 0x0020
-#define NGX_HTTP_MKCOL 0x0040
-#define NGX_HTTP_COPY 0x0080
-#define NGX_HTTP_MOVE 0x0100
-#define NGX_HTTP_OPTIONS 0x0200
-#define NGX_HTTP_PROPFIND 0x0400
-#define NGX_HTTP_PROPPATCH 0x0800
-#define NGX_HTTP_LOCK 0x1000
-#define NGX_HTTP_UNLOCK 0x2000
-#define NGX_HTTP_PATCH 0x4000
-#define NGX_HTTP_TRACE 0x8000
+#define NGX_HTTP_UNKNOWN 0x00000001
+#define NGX_HTTP_GET 0x00000002
+#define NGX_HTTP_HEAD 0x00000004
+#define NGX_HTTP_POST 0x00000008
+#define NGX_HTTP_PUT 0x00000010
+#define NGX_HTTP_DELETE 0x00000020
+#define NGX_HTTP_MKCOL 0x00000040
+#define NGX_HTTP_COPY 0x00000080
+#define NGX_HTTP_MOVE 0x00000100
+#define NGX_HTTP_OPTIONS 0x00000200
+#define NGX_HTTP_PROPFIND 0x00000400
+#define NGX_HTTP_PROPPATCH 0x00000800
+#define NGX_HTTP_LOCK 0x00001000
+#define NGX_HTTP_UNLOCK 0x00002000
+#define NGX_HTTP_PATCH 0x00004000
+#define NGX_HTTP_TRACE 0x00008000
+#define NGX_HTTP_CONNECT 0x00010000
#define NGX_HTTP_CONNECTION_CLOSE 1
#define NGX_HTTP_CONNECTION_KEEP_ALIVE 2
@@ -473,9 +474,6 @@ struct ngx_http_request_s {
/* URI with "+" */
unsigned plus_in_uri:1;
- /* URI with " " */
- unsigned space_in_uri:1;
-
/* URI with empty path */
unsigned empty_path_in_uri:1;
diff --git a/src/http/v2/ngx_http_v2.c b/src/http/v2/ngx_http_v2.c
index 3611a2e50..3bef002bd 100644
--- a/src/http/v2/ngx_http_v2.c
+++ b/src/http/v2/ngx_http_v2.c
@@ -3457,7 +3457,7 @@ ngx_http_v2_validate_header(ngx_http_request_t *r, ngx_http_v2_header_t *header)
continue;
}
- if (ch == '\0' || ch == LF || ch == CR || ch == ':'
+ if (ch <= 0x20 || ch == 0x7f || ch == ':'
|| (ch >= 'A' && ch <= 'Z'))
{
ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
@@ -3606,7 +3606,8 @@ ngx_http_v2_parse_method(ngx_http_request_t *r, ngx_str_t *value)
{ 4, "LOCK", NGX_HTTP_LOCK },
{ 6, "UNLOCK", NGX_HTTP_UNLOCK },
{ 5, "PATCH", NGX_HTTP_PATCH },
- { 5, "TRACE", NGX_HTTP_TRACE }
+ { 5, "TRACE", NGX_HTTP_TRACE },
+ { 7, "CONNECT", NGX_HTTP_CONNECT }
}, *test;
if (r->method_name.len) {
diff --git a/src/os/unix/ngx_readv_chain.c b/src/os/unix/ngx_readv_chain.c
index a3577ce19..b1ae4b51d 100644
--- a/src/os/unix/ngx_readv_chain.c
+++ b/src/os/unix/ngx_readv_chain.c
@@ -96,7 +96,7 @@ ngx_readv_chain(ngx_connection_t *c, ngx_chain_t *chain, off_t limit)
iov->iov_len += n;
} else {
- if (vec.nelts >= IOV_MAX) {
+ if (vec.nelts == vec.nalloc) {
break;
}
diff --git a/src/os/win32/ngx_win32_init.c b/src/os/win32/ngx_win32_init.c
index 3249fb293..de66a44eb 100644
--- a/src/os/win32/ngx_win32_init.c
+++ b/src/os/win32/ngx_win32_init.c
@@ -295,7 +295,7 @@ ngx_os_status(ngx_log_t *log)
osviex_stub = (ngx_osviex_stub_t *) &osvi.wServicePackMinor;
ngx_log_error(NGX_LOG_INFO, log, 0,
- "OS: %ud build:%ud, \"%s\", suite:%Xd, type:%ud",
+ "OS: %ui build:%ud, \"%s\", suite:%Xd, type:%ud",
ngx_win32_version, osvi.dwBuildNumber, osvi.szCSDVersion,
osviex_stub->wSuiteMask, osviex_stub->wProductType);
@@ -305,7 +305,7 @@ ngx_os_status(ngx_log_t *log)
/* Win9x build */
ngx_log_error(NGX_LOG_INFO, log, 0,
- "OS: %u build:%ud.%ud.%ud, \"%s\"",
+ "OS: %ui build:%ud.%ud.%ud, \"%s\"",
ngx_win32_version,
osvi.dwBuildNumber >> 24,
(osvi.dwBuildNumber >> 16) & 0xff,
@@ -321,7 +321,7 @@ ngx_os_status(ngx_log_t *log)
* and we do not support VER_PLATFORM_WIN32s at all
*/
- ngx_log_error(NGX_LOG_INFO, log, 0, "OS: %ud build:%ud, \"%s\"",
+ ngx_log_error(NGX_LOG_INFO, log, 0, "OS: %ui build:%ud, \"%s\"",
ngx_win32_version, osvi.dwBuildNumber,
osvi.szCSDVersion);
}
diff --git a/src/os/win32/ngx_wsarecv_chain.c b/src/os/win32/ngx_wsarecv_chain.c
index 87f023911..4f95d5a2b 100644
--- a/src/os/win32/ngx_wsarecv_chain.c
+++ b/src/os/win32/ngx_wsarecv_chain.c
@@ -10,7 +10,7 @@
#include <ngx_event.h>
-#define NGX_WSABUFS 8
+#define NGX_WSABUFS 64
ssize_t
@@ -57,6 +57,10 @@ ngx_wsarecv_chain(ngx_connection_t *c, ngx_chain_t *chain, off_t limit)
wsabuf->len += n;
} else {
+ if (vec.nelts == vec.nalloc) {
+ break;
+ }
+
wsabuf = ngx_array_push(&vec);
if (wsabuf == NULL) {
return NGX_ERROR;
diff --git a/src/os/win32/ngx_wsasend_chain.c b/src/os/win32/ngx_wsasend_chain.c
index e2dde22c9..cd50e710c 100644
--- a/src/os/win32/ngx_wsasend_chain.c
+++ b/src/os/win32/ngx_wsasend_chain.c
@@ -10,7 +10,7 @@
#include <ngx_event.h>
-#define NGX_WSABUFS 8
+#define NGX_WSABUFS 64
ngx_chain_t *
@@ -47,7 +47,7 @@ ngx_wsasend_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit)
vec.elts = wsabufs;
vec.size = sizeof(WSABUF);
- vec.nalloc = NGX_WSABUFS;
+ vec.nalloc = ngx_min(NGX_WSABUFS, ngx_max_wsabufs);
vec.pool = c->pool;
for ( ;; ) {
@@ -59,10 +59,8 @@ ngx_wsasend_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit)
/* create the WSABUF and coalesce the neighbouring bufs */
- for (cl = in;
- cl && vec.nelts < ngx_max_wsabufs && send < limit;
- cl = cl->next)
- {
+ for (cl = in; cl && send < limit; cl = cl->next) {
+
if (ngx_buf_special(cl->buf)) {
continue;
}
@@ -77,6 +75,10 @@ ngx_wsasend_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit)
wsabuf->len += cl->buf->last - cl->buf->pos;
} else {
+ if (vec.nelts == vec.nalloc) {
+ break;
+ }
+
wsabuf = ngx_array_push(&vec);
if (wsabuf == NULL) {
return NGX_CHAIN_ERROR;
@@ -169,7 +171,7 @@ ngx_overlapped_wsasend_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit)
vec.elts = wsabufs;
vec.nelts = 0;
vec.size = sizeof(WSABUF);
- vec.nalloc = NGX_WSABUFS;
+ vec.nalloc = ngx_min(NGX_WSABUFS, ngx_max_wsabufs);
vec.pool = c->pool;
send = 0;
@@ -178,10 +180,8 @@ ngx_overlapped_wsasend_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit)
/* create the WSABUF and coalesce the neighbouring bufs */
- for (cl = in;
- cl && vec.nelts < ngx_max_wsabufs && send < limit;
- cl = cl->next)
- {
+ for (cl = in; cl && send < limit; cl = cl->next) {
+
if (ngx_buf_special(cl->buf)) {
continue;
}
@@ -196,6 +196,10 @@ ngx_overlapped_wsasend_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit)
wsabuf->len += cl->buf->last - cl->buf->pos;
} else {
+ if (vec.nelts == vec.nalloc) {
+ break;
+ }
+
wsabuf = ngx_array_push(&vec);
if (wsabuf == NULL) {
return NGX_CHAIN_ERROR;