summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGES35
-rw-r--r--CHANGES.ru36
-rw-r--r--auto/cc/msvc1
-rw-r--r--src/core/nginx.h4
-rw-r--r--src/core/ngx_connection.c12
-rw-r--r--src/core/ngx_resolver.c22
-rw-r--r--src/event/ngx_event_openssl.c14
-rw-r--r--src/event/ngx_event_openssl.h2
-rw-r--r--src/http/modules/ngx_http_access_module.c6
-rw-r--r--src/http/modules/ngx_http_fastcgi_module.c2
-rw-r--r--src/http/modules/ngx_http_gzip_static_module.c2
-rw-r--r--src/http/modules/ngx_http_mp4_module.c2
-rw-r--r--src/http/modules/ngx_http_proxy_module.c2
-rw-r--r--src/http/modules/ngx_http_range_filter_module.c12
-rw-r--r--src/http/modules/ngx_http_scgi_module.c4
-rw-r--r--src/http/modules/ngx_http_ssl_module.c3
-rw-r--r--src/http/modules/ngx_http_uwsgi_module.c4
-rw-r--r--src/http/ngx_http_core_module.c8
-rw-r--r--src/http/ngx_http_request.c2
-rw-r--r--src/http/ngx_http_request_body.c8
-rw-r--r--src/http/ngx_http_spdy.c64
-rw-r--r--src/http/ngx_http_spdy.h3
-rw-r--r--src/http/ngx_http_spdy_filter_module.c5
-rw-r--r--src/http/ngx_http_upstream.c8
-rw-r--r--src/os/unix/ngx_freebsd_sendfile_chain.c2
-rw-r--r--src/os/unix/ngx_linux_sendfile_chain.c4
26 files changed, 188 insertions, 79 deletions
diff --git a/CHANGES b/CHANGES
index e53487e69..365355e7d 100644
--- a/CHANGES
+++ b/CHANGES
@@ -1,4 +1,39 @@
+Changes with nginx 1.5.11 04 Mar 2014
+
+ *) Security: memory corruption might occur in a worker process on 32-bit
+ platforms while handling a specially crafted request by
+ ngx_http_spdy_module, potentially resulting in arbitrary code
+ execution (CVE-2014-0088); the bug had appeared in 1.5.10.
+ Thanks to Lucas Molas, researcher at Programa STIC, Fundación Dr.
+ Manuel Sadosky, Buenos Aires, Argentina.
+
+ *) Feature: the $ssl_session_reused variable.
+
+ *) Bugfix: the "client_max_body_size" directive might not work when
+ reading a request body using chunked transfer encoding; the bug had
+ appeared in 1.3.9.
+ Thanks to Lucas Molas.
+
+ *) Bugfix: a segmentation fault might occur in a worker process when
+ proxying WebSocket connections.
+
+ *) Bugfix: a segmentation fault might occur in a worker process if the
+ ngx_http_spdy_module was used on 32-bit platforms; the bug had
+ appeared in 1.5.10.
+
+ *) Bugfix: the $upstream_status variable might contain wrong data if the
+ "proxy_cache_use_stale" or "proxy_cache_revalidate" directives were
+ used.
+ Thanks to Piotr Sikora.
+
+ *) Bugfix: a segmentation fault might occur in a worker process if
+ errors with code 400 were redirected to a named location using the
+ "error_page" directive.
+
+ *) Bugfix: nginx/Windows could not be built with Visual Studio 2013.
+
+
Changes with nginx 1.5.10 04 Feb 2014
*) Feature: the ngx_http_spdy_module now uses SPDY 3.1 protocol.
diff --git a/CHANGES.ru b/CHANGES.ru
index 006b364a5..2d79bee66 100644
--- a/CHANGES.ru
+++ b/CHANGES.ru
@@ -1,4 +1,40 @@
+Изменения в nginx 1.5.11 04.03.2014
+
+ *) Безопасность: при обработке специально созданного запроса модулем
+ ngx_http_spdy_module на 32-битных платформах могла повреждаться
+ память рабочего процесса, что потенциально могло приводить к
+ выполнению произвольного кода (CVE-2014-0088); ошибка появилась в
+ 1.5.10.
+ Спасибо Lucas Molas из Programa STIC, Fundación Dr. Manuel Sadosky,
+ Buenos Aires, Argentina.
+
+ *) Добавление: переменная $ssl_session_reused.
+
+ *) Исправление: директива client_max_body_size могла не работать при
+ чтении тела запроса с использованием chunked transfer encoding;
+ ошибка появилась в 1.3.9.
+ Спасибо Lucas Molas.
+
+ *) Исправление: при проксировании WebSocket-соединений в рабочем
+ процессе мог произойти segmentation fault.
+
+ *) Исправление: в рабочем процессе мог произойти segmentation fault,
+ если использовался модуль ngx_http_spdy_module на 32-битных
+ платформах; ошибка появилась в 1.5.10.
+
+ *) Исправление: значение переменной $upstream_status могло быть
+ неверным, если использовались директивы proxy_cache_use_stale или
+ proxy_cache_revalidate.
+ Спасибо Piotr Sikora.
+
+ *) Исправление: в рабочем процессе мог произойти segmentation fault,
+ если ошибки с кодом 400 с помощью директивы error_page
+ перенаправлялись в именованный location.
+
+ *) Исправление: nginx/Windows не собирался с Visual Studio 2013.
+
+
Изменения в nginx 1.5.10 04.02.2014
*) Добавление: модуль ngx_http_spdy_module теперь использует протокол
diff --git a/auto/cc/msvc b/auto/cc/msvc
index 1bf675e19..6cb8b3d58 100644
--- a/auto/cc/msvc
+++ b/auto/cc/msvc
@@ -106,6 +106,7 @@ fi
# precompiled headers
CORE_DEPS="$CORE_DEPS $NGX_OBJS/ngx_config.pch"
+CORE_LINK="$NGX_OBJS/ngx_pch.obj"
NGX_PCH="$NGX_OBJS/ngx_config.pch"
NGX_BUILD_PCH="-Ycngx_config.h -Fp$NGX_OBJS/ngx_config.pch"
NGX_USE_PCH="-Yungx_config.h -Fp$NGX_OBJS/ngx_config.pch"
diff --git a/src/core/nginx.h b/src/core/nginx.h
index 71a71230c..8ab0e8890 100644
--- a/src/core/nginx.h
+++ b/src/core/nginx.h
@@ -9,8 +9,8 @@
#define _NGINX_H_INCLUDED_
-#define nginx_version 1005010
-#define NGINX_VERSION "1.5.10"
+#define nginx_version 1005011
+#define NGINX_VERSION "1.5.11"
#define NGINX_VER "nginx/" NGINX_VERSION
#define NGINX_VAR "NGINX"
diff --git a/src/core/ngx_connection.c b/src/core/ngx_connection.c
index 15f4f3c90..6b6e3b3a5 100644
--- a/src/core/ngx_connection.c
+++ b/src/core/ngx_connection.c
@@ -129,7 +129,7 @@ ngx_set_inherited_sockets(ngx_cycle_t *cycle)
#if (NGX_HAVE_INET6)
case AF_INET6:
ls[i].addr_text_max_len = NGX_INET6_ADDRSTRLEN;
- len = NGX_INET6_ADDRSTRLEN + sizeof(":65535") - 1;
+ len = NGX_INET6_ADDRSTRLEN + sizeof("[]:65535") - 1;
break;
#endif
@@ -244,7 +244,7 @@ ngx_set_inherited_sockets(ngx_cycle_t *cycle)
if (getsockopt(ls[i].fd, SOL_SOCKET, SO_ACCEPTFILTER, &af, &olen)
== -1)
{
- err = ngx_errno;
+ err = ngx_socket_errno;
if (err == NGX_EINVAL) {
continue;
@@ -277,7 +277,7 @@ ngx_set_inherited_sockets(ngx_cycle_t *cycle)
if (getsockopt(ls[i].fd, IPPROTO_TCP, TCP_DEFER_ACCEPT, &timeout, &olen)
== -1)
{
- err = ngx_errno;
+ err = ngx_socket_errno;
if (err == NGX_EOPNOTSUPP) {
continue;
@@ -661,7 +661,7 @@ ngx_configure_listening_sockets(ngx_cycle_t *cycle)
if (setsockopt(ls[i].fd, SOL_SOCKET, SO_ACCEPTFILTER, NULL, 0)
== -1)
{
- ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
+ ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno,
"setsockopt(SO_ACCEPTFILTER, NULL) "
"for %V failed, ignored",
&ls[i].addr_text);
@@ -688,7 +688,7 @@ ngx_configure_listening_sockets(ngx_cycle_t *cycle)
&af, sizeof(struct accept_filter_arg))
== -1)
{
- ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
+ ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno,
"setsockopt(SO_ACCEPTFILTER, \"%s\") "
"for %V failed, ignored",
ls[i].accept_filter, &ls[i].addr_text);
@@ -721,7 +721,7 @@ ngx_configure_listening_sockets(ngx_cycle_t *cycle)
&value, sizeof(int))
== -1)
{
- ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
+ ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno,
"setsockopt(TCP_DEFER_ACCEPT, %d) for %V failed, "
"ignored",
value, &ls[i].addr_text);
diff --git a/src/core/ngx_resolver.c b/src/core/ngx_resolver.c
index abf82d85b..7fab50abc 100644
--- a/src/core/ngx_resolver.c
+++ b/src/core/ngx_resolver.c
@@ -3037,14 +3037,7 @@ ngx_udp_connect(ngx_udp_connection_t *uc)
ngx_log_error(NGX_LOG_ALERT, &uc->log, ngx_socket_errno,
ngx_nonblocking_n " failed");
- ngx_free_connection(c);
-
- if (ngx_close_socket(s) == -1) {
- ngx_log_error(NGX_LOG_ALERT, &uc->log, ngx_socket_errno,
- ngx_close_socket_n " failed");
- }
-
- return NGX_ERROR;
+ goto failed;
}
rev = c->read;
@@ -3079,7 +3072,7 @@ ngx_udp_connect(ngx_udp_connection_t *uc)
ngx_log_error(NGX_LOG_CRIT, &uc->log, ngx_socket_errno,
"connect() failed");
- return NGX_ERROR;
+ goto failed;
}
/* UDP sockets are always ready to write */
@@ -3093,16 +3086,23 @@ ngx_udp_connect(ngx_udp_connection_t *uc)
/* eventport event type has no meaning: oneshot only */
if (ngx_add_event(rev, NGX_READ_EVENT, event) != NGX_OK) {
- return NGX_ERROR;
+ goto failed;
}
} else {
/* rtsig */
if (ngx_add_conn(c) == NGX_ERROR) {
- return NGX_ERROR;
+ goto failed;
}
}
return NGX_OK;
+
+failed:
+
+ ngx_close_connection(c);
+ uc->connection = NULL;
+
+ return NGX_ERROR;
}
diff --git a/src/event/ngx_event_openssl.c b/src/event/ngx_event_openssl.c
index cbe4136a1..28e7aa509 100644
--- a/src/event/ngx_event_openssl.c
+++ b/src/event/ngx_event_openssl.c
@@ -2529,6 +2529,20 @@ ngx_ssl_get_session_id(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s)
ngx_int_t
+ngx_ssl_get_session_reused(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s)
+{
+ if (SSL_session_reused(c->ssl->connection)) {
+ ngx_str_set(s, "r");
+
+ } else {
+ ngx_str_set(s, ".");
+ }
+
+ return NGX_OK;
+}
+
+
+ngx_int_t
ngx_ssl_get_raw_certificate(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s)
{
size_t len;
diff --git a/src/event/ngx_event_openssl.h b/src/event/ngx_event_openssl.h
index 907639e83..b7f850019 100644
--- a/src/event/ngx_event_openssl.h
+++ b/src/event/ngx_event_openssl.h
@@ -157,6 +157,8 @@ ngx_int_t ngx_ssl_get_cipher_name(ngx_connection_t *c, ngx_pool_t *pool,
ngx_str_t *s);
ngx_int_t ngx_ssl_get_session_id(ngx_connection_t *c, ngx_pool_t *pool,
ngx_str_t *s);
+ngx_int_t ngx_ssl_get_session_reused(ngx_connection_t *c, ngx_pool_t *pool,
+ ngx_str_t *s);
ngx_int_t ngx_ssl_get_raw_certificate(ngx_connection_t *c, ngx_pool_t *pool,
ngx_str_t *s);
ngx_int_t ngx_ssl_get_certificate(ngx_connection_t *c, ngx_pool_t *pool,
diff --git a/src/http/modules/ngx_http_access_module.c b/src/http/modules/ngx_http_access_module.c
index fcee40ca0..c553e4610 100644
--- a/src/http/modules/ngx_http_access_module.c
+++ b/src/http/modules/ngx_http_access_module.c
@@ -259,7 +259,11 @@ ngx_http_access_unix(ngx_http_request_t *r, ngx_http_access_loc_conf_t *alcf)
rule_un = alcf->rules_un->elts;
for (i = 0; i < alcf->rules_un->nelts; i++) {
- return ngx_http_access_found(r, rule_un[i].deny);
+
+ /* TODO: check path */
+ if (1) {
+ return ngx_http_access_found(r, rule_un[i].deny);
+ }
}
return NGX_DECLINED;
diff --git a/src/http/modules/ngx_http_fastcgi_module.c b/src/http/modules/ngx_http_fastcgi_module.c
index 5bcf6ef8c..24dbbf663 100644
--- a/src/http/modules/ngx_http_fastcgi_module.c
+++ b/src/http/modules/ngx_http_fastcgi_module.c
@@ -1584,7 +1584,7 @@ ngx_http_fastcgi_process_header(ngx_http_request_t *r)
ngx_str_set(&u->headers_in.status_line, "200 OK");
}
- if (u->state) {
+ if (u->state && u->state->status == 0) {
u->state->status = u->headers_in.status_n;
}
diff --git a/src/http/modules/ngx_http_gzip_static_module.c b/src/http/modules/ngx_http_gzip_static_module.c
index 6e777619b..1746e5504 100644
--- a/src/http/modules/ngx_http_gzip_static_module.c
+++ b/src/http/modules/ngx_http_gzip_static_module.c
@@ -38,7 +38,7 @@ static ngx_conf_enum_t ngx_http_gzip_static[] = {
static ngx_command_t ngx_http_gzip_static_commands[] = {
{ ngx_string("gzip_static"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
+ NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
ngx_conf_set_enum_slot,
NGX_HTTP_LOC_CONF_OFFSET,
offsetof(ngx_http_gzip_static_conf_t, enable),
diff --git a/src/http/modules/ngx_http_mp4_module.c b/src/http/modules/ngx_http_mp4_module.c
index c29ab1ce5..426a0b97f 100644
--- a/src/http/modules/ngx_http_mp4_module.c
+++ b/src/http/modules/ngx_http_mp4_module.c
@@ -2481,7 +2481,7 @@ ngx_http_mp4_update_stsc_atom(ngx_http_mp4_file_t *mp4,
n = (next_chunk - chunk) * samples;
- if (start_sample <= n) {
+ if (start_sample < n) {
goto found;
}
diff --git a/src/http/modules/ngx_http_proxy_module.c b/src/http/modules/ngx_http_proxy_module.c
index 93469984c..8ee32f491 100644
--- a/src/http/modules/ngx_http_proxy_module.c
+++ b/src/http/modules/ngx_http_proxy_module.c
@@ -1362,7 +1362,7 @@ ngx_http_proxy_process_status_line(ngx_http_request_t *r)
return NGX_OK;
}
- if (u->state) {
+ if (u->state && u->state->status == 0) {
u->state->status = ctx->status.code;
}
diff --git a/src/http/modules/ngx_http_range_filter_module.c b/src/http/modules/ngx_http_range_filter_module.c
index 6143a8786..bcc64fd30 100644
--- a/src/http/modules/ngx_http_range_filter_module.c
+++ b/src/http/modules/ngx_http_range_filter_module.c
@@ -432,7 +432,9 @@ ngx_http_range_multipart_header(ngx_http_request_t *r,
+ r->headers_out.content_type.len
+ sizeof(CRLF "Content-Range: bytes ") - 1;
- if (r->headers_out.charset.len) {
+ if (r->headers_out.content_type_len == r->headers_out.content_type.len
+ && r->headers_out.charset.len)
+ {
len += sizeof("; charset=") - 1 + r->headers_out.charset.len;
}
@@ -451,7 +453,9 @@ ngx_http_range_multipart_header(ngx_http_request_t *r,
* "Content-Range: bytes "
*/
- if (r->headers_out.charset.len) {
+ if (r->headers_out.content_type_len == r->headers_out.content_type.len
+ && r->headers_out.charset.len)
+ {
ctx->boundary_header.len = ngx_sprintf(ctx->boundary_header.data,
CRLF "--%0muA" CRLF
"Content-Type: %V; charset=%V" CRLF
@@ -461,8 +465,6 @@ ngx_http_range_multipart_header(ngx_http_request_t *r,
&r->headers_out.charset)
- ctx->boundary_header.data;
- r->headers_out.charset.len = 0;
-
} else if (r->headers_out.content_type.len) {
ctx->boundary_header.len = ngx_sprintf(ctx->boundary_header.data,
CRLF "--%0muA" CRLF
@@ -501,6 +503,8 @@ ngx_http_range_multipart_header(ngx_http_request_t *r,
r->headers_out.content_type_len = r->headers_out.content_type.len;
+ r->headers_out.charset.len = 0;
+
/* the size of the last boundary CRLF "--0123456789--" CRLF */
len = sizeof(CRLF "--") - 1 + NGX_ATOMIC_T_LEN + sizeof("--" CRLF) - 1;
diff --git a/src/http/modules/ngx_http_scgi_module.c b/src/http/modules/ngx_http_scgi_module.c
index 70f6ac1de..884cb500a 100644
--- a/src/http/modules/ngx_http_scgi_module.c
+++ b/src/http/modules/ngx_http_scgi_module.c
@@ -885,7 +885,7 @@ ngx_http_scgi_process_status_line(ngx_http_request_t *r)
return ngx_http_scgi_process_header(r);
}
- if (u->state) {
+ if (u->state && u->state->status == 0) {
u->state->status = status->code;
}
@@ -1013,7 +1013,7 @@ ngx_http_scgi_process_header(ngx_http_request_t *r)
ngx_str_set(&u->headers_in.status_line, "200 OK");
}
- if (u->state) {
+ if (u->state && u->state->status == 0) {
u->state->status = u->headers_in.status_n;
}
diff --git a/src/http/modules/ngx_http_ssl_module.c b/src/http/modules/ngx_http_ssl_module.c
index df1e55ee9..206f58d25 100644
--- a/src/http/modules/ngx_http_ssl_module.c
+++ b/src/http/modules/ngx_http_ssl_module.c
@@ -270,6 +270,9 @@ static ngx_http_variable_t ngx_http_ssl_vars[] = {
{ ngx_string("ssl_session_id"), NULL, ngx_http_ssl_variable,
(uintptr_t) ngx_ssl_get_session_id, NGX_HTTP_VAR_CHANGEABLE, 0 },
+ { ngx_string("ssl_session_reused"), NULL, ngx_http_ssl_variable,
+ (uintptr_t) ngx_ssl_get_session_reused, NGX_HTTP_VAR_CHANGEABLE, 0 },
+
{ ngx_string("ssl_client_cert"), NULL, ngx_http_ssl_variable,
(uintptr_t) ngx_ssl_get_certificate, NGX_HTTP_VAR_CHANGEABLE, 0 },
diff --git a/src/http/modules/ngx_http_uwsgi_module.c b/src/http/modules/ngx_http_uwsgi_module.c
index f55e606c8..17dfc3b3a 100644
--- a/src/http/modules/ngx_http_uwsgi_module.c
+++ b/src/http/modules/ngx_http_uwsgi_module.c
@@ -1017,7 +1017,7 @@ ngx_http_uwsgi_process_status_line(ngx_http_request_t *r)
return ngx_http_uwsgi_process_header(r);
}
- if (u->state) {
+ if (u->state && u->state->status == 0) {
u->state->status = status->code;
}
@@ -1145,7 +1145,7 @@ ngx_http_uwsgi_process_header(ngx_http_request_t *r)
ngx_str_set(&u->headers_in.status_line, "200 OK");
}
- if (u->state) {
+ if (u->state && u->state->status == 0) {
u->state->status = u->headers_in.status_n;
}
diff --git a/src/http/ngx_http_core_module.c b/src/http/ngx_http_core_module.c
index 8abf864d5..74a448a88 100644
--- a/src/http/ngx_http_core_module.c
+++ b/src/http/ngx_http_core_module.c
@@ -2632,6 +2632,14 @@ ngx_http_named_location(ngx_http_request_t *r, ngx_str_t *name)
return NGX_DONE;
}
+ if (r->uri.len == 0) {
+ ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
+ "empty URI in redirect to named location \"%V\"", name);
+
+ ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
+ return NGX_DONE;
+ }
+
cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
if (cscf->named_locations) {
diff --git a/src/http/ngx_http_request.c b/src/http/ngx_http_request.c
index 0bb1b8cde..5f2cf7d39 100644
--- a/src/http/ngx_http_request.c
+++ b/src/http/ngx_http_request.c
@@ -2707,7 +2707,7 @@ ngx_http_test_reading(ngx_http_request_t *r)
if (getsockopt(c->fd, SOL_SOCKET, SO_ERROR, (void *) &err, &len)
== -1)
{
- err = ngx_errno;
+ err = ngx_socket_errno;
}
goto closed;
diff --git a/src/http/ngx_http_request_body.c b/src/http/ngx_http_request_body.c
index 94cdbeed6..bbf16fd25 100644
--- a/src/http/ngx_http_request_body.c
+++ b/src/http/ngx_http_request_body.c
@@ -953,13 +953,13 @@ ngx_http_request_body_chunked_filter(ngx_http_request_t *r, ngx_chain_t *in)
if (clcf->client_max_body_size
&& clcf->client_max_body_size
- < r->headers_in.content_length_n + rb->chunked->size)
+ - r->headers_in.content_length_n < rb->chunked->size)
{
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
"client intended to send too large chunked "
- "body: %O bytes",
- r->headers_in.content_length_n
- + rb->chunked->size);
+ "body: %O+%O bytes",
+ r->headers_in.content_length_n,
+ rb->chunked->size);
r->lingering_close = 1;
diff --git a/src/http/ngx_http_spdy.c b/src/http/ngx_http_spdy.c
index 20755f490..4005bfbe7 100644
--- a/src/http/ngx_http_spdy.c
+++ b/src/http/ngx_http_spdy.c
@@ -1038,7 +1038,7 @@ ngx_http_spdy_state_headers(ngx_http_spdy_connection_t *sc, u_char *pos,
"spdy HEADERS block consists of %ui entries",
sc->entries);
- if (ngx_list_init(&r->headers_in.headers, r->pool, sc->entries + 3,
+ if (ngx_list_init(&r->headers_in.headers, r->pool, 20,
sizeof(ngx_table_elt_t))
!= NGX_OK)
{
@@ -2325,7 +2325,7 @@ static ngx_int_t
ngx_http_spdy_parse_header(ngx_http_request_t *r)
{
u_char *p, *end, ch;
- ngx_uint_t len, hash;
+ ngx_uint_t hash;
ngx_http_core_srv_conf_t *cscf;
enum {
@@ -2348,9 +2348,9 @@ ngx_http_spdy_parse_header(ngx_http_request_t *r)
return NGX_AGAIN;
}
- len = ngx_spdy_frame_parse_uint32(p);
+ r->lowcase_index = ngx_spdy_frame_parse_uint32(p);
- if (!len) {
+ if (r->lowcase_index == 0) {
return NGX_HTTP_PARSE_INVALID_HEADER;
}
@@ -2359,8 +2359,6 @@ ngx_http_spdy_parse_header(ngx_http_request_t *r)
p += NGX_SPDY_NV_NLEN_SIZE;
- r->header_name_end = p + len;
- r->lowcase_index = len;
r->invalid_header = 0;
state = sw_name;
@@ -2369,16 +2367,16 @@ ngx_http_spdy_parse_header(ngx_http_request_t *r)
case sw_name:
- if (r->header_name_end > end) {
+ if ((ngx_uint_t) (end - p) < r->lowcase_index) {
break;
}
cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
r->header_name_start = p;
+ r->header_name_end = p + r->lowcase_index;
if (p[0] == ':') {
- r->lowcase_index--;
p++;
}
@@ -2425,29 +2423,26 @@ ngx_http_spdy_parse_header(ngx_http_request_t *r)
break;
}
- len = ngx_spdy_frame_parse_uint32(p);
+ r->lowcase_index = ngx_spdy_frame_parse_uint32(p);
/* null-terminate header name */
*p = '\0';
p += NGX_SPDY_NV_VLEN_SIZE;
- r->header_end = p + len;
-
state = sw_value;
/* fall through */
case sw_value:
- if (r->header_end > end) {
+ if ((ngx_uint_t) (end - p) < r->lowcase_index) {
break;
}
r->header_start = p;
- for ( /* void */ ; p != r->header_end; p++) {
-
+ while (r->lowcase_index--) {
ch = *p;
if (ch == '\0') {
@@ -2456,7 +2451,7 @@ ngx_http_spdy_parse_header(ngx_http_request_t *r)
return NGX_ERROR;
}
- r->header_size = p - r->header_start;
+ r->header_end = p;
r->header_in->pos = p + 1;
return NGX_OK;
@@ -2465,9 +2460,11 @@ ngx_http_spdy_parse_header(ngx_http_request_t *r)
if (ch == CR || ch == LF) {
return NGX_HTTP_PARSE_INVALID_HEADER;
}
+
+ p++;
}
- r->header_size = p - r->header_start;
+ r->header_end = p;
r->header_in->pos = p;
r->state = 0;
@@ -2526,13 +2523,6 @@ ngx_http_spdy_alloc_large_header_buffer(ngx_http_request_t *r)
buf->last = ngx_cpymem(new, old, rest);
}
- if (r->header_name_end > old) {
- r->header_name_end = new + (r->header_name_end - old);
-
- } else if (r->header_end > old) {
- r->header_end = new + (r->header_end - old);
- }
-
r->header_in = buf;
stream->header_buffers++;
@@ -2563,14 +2553,14 @@ ngx_http_spdy_handle_request_header(ngx_http_request_t *r)
}
if (r->header_name_start[0] == ':') {
+ r->header_name_start++;
+
for (i = 0; i < NGX_SPDY_REQUEST_HEADERS; i++) {
sh = &ngx_http_spdy_request_headers[i];
if (sh->hash != r->header_hash
- || sh->len != r->lowcase_index
- || ngx_strncmp(sh->header, &r->header_name_start[1],
- r->lowcase_index)
- != 0)
+ || sh->len != r->header_name_end - r->header_name_start
+ || ngx_strncmp(sh->header, r->header_name_start, sh->len) != 0)
{
continue;
}
@@ -2590,10 +2580,10 @@ ngx_http_spdy_handle_request_header(ngx_http_request_t *r)
h->hash = r->header_hash;
- h->key.len = r->lowcase_index;
+ h->key.len = r->header_name_end - r->header_name_start;
h->key.data = r->header_name_start;
- h->value.len = r->header_size;
+ h->value.len = r->header_end - r->header_start;
h->value.data = r->header_start;
h->lowcase_key = h->key.data;
@@ -2653,7 +2643,7 @@ ngx_http_spdy_parse_method(ngx_http_request_t *r)
return NGX_HTTP_PARSE_INVALID_HEADER;
}
- len = r->header_size;
+ len = r->header_end - r->header_start;
r->method_name.len = len;
r->method_name.data = r->header_start;
@@ -2733,10 +2723,10 @@ ngx_http_spdy_parse_host(ngx_http_request_t *r)
h->hash = r->header_hash;
- h->key.len = r->lowcase_index;
- h->key.data = &r->header_name_start[1];
+ h->key.len = r->header_name_end - r->header_name_start;
+ h->key.data = r->header_name_start;
- h->value.len = r->header_size;
+ h->value.len = r->header_end - r->header_start;
h->value.data = r->header_start;
h->lowcase_key = h->key.data;
@@ -2778,7 +2768,7 @@ ngx_http_spdy_parse_version(ngx_http_request_t *r)
p = r->header_start;
- if (r->header_size < 8 || !(ngx_str5cmp(p, 'H', 'T', 'T', 'P', '/'))) {
+ if (r->header_end - p < 8 || !(ngx_str5cmp(p, 'H', 'T', 'T', 'P', '/'))) {
return NGX_HTTP_PARSE_INVALID_REQUEST;
}
@@ -2794,6 +2784,10 @@ ngx_http_spdy_parse_version(ngx_http_request_t *r)
ch = *p;
+ if (ch == '.') {
+ break;
+ }
+
if (ch < '0' || ch > '9') {
return NGX_HTTP_PARSE_INVALID_REQUEST;
}
@@ -2824,7 +2818,7 @@ ngx_http_spdy_parse_version(ngx_http_request_t *r)
r->http_minor = r->http_minor * 10 + ch - '0';
}
- r->http_protocol.len = r->header_size;
+ r->http_protocol.len = r->header_end - r->header_start;
r->http_protocol.data = r->header_start;
r->http_version = r->http_major * 1000 + r->http_minor;
diff --git a/src/http/ngx_http_spdy.h b/src/http/ngx_http_spdy.h
index b98b4d85a..55aceda89 100644
--- a/src/http/ngx_http_spdy.h
+++ b/src/http/ngx_http_spdy.h
@@ -174,6 +174,9 @@ ngx_http_spdy_queue_frame(ngx_http_spdy_connection_t *sc,
for (out = &sc->last_out; *out; out = &(*out)->next)
{
+ /*
+ * NB: higher values represent lower priorities.
+ */
if (frame->priority >= (*out)->priority) {
break;
}
diff --git a/src/http/ngx_http_spdy_filter_module.c b/src/http/ngx_http_spdy_filter_module.c
index 8a3f0a3c8..92c760243 100644
--- a/src/http/ngx_http_spdy_filter_module.c
+++ b/src/http/ngx_http_spdy_filter_module.c
@@ -967,7 +967,10 @@ ngx_http_spdy_waiting_queue(ngx_http_spdy_connection_t *sc,
{
s = ngx_queue_data(q, ngx_http_spdy_stream_t, queue);
- if (s->priority >= stream->priority) {
+ /*
+ * NB: higher values represent lower priorities.
+ */
+ if (stream->priority >= s->priority) {
break;
}
}
diff --git a/src/http/ngx_http_upstream.c b/src/http/ngx_http_upstream.c
index 26b576441..cf9ca0d5c 100644
--- a/src/http/ngx_http_upstream.c
+++ b/src/http/ngx_http_upstream.c
@@ -715,7 +715,7 @@ ngx_http_upstream_cache(ngx_http_request_t *r, ngx_http_upstream_t *u)
if (r->cache->header_start + 256 >= u->conf->buffer_size) {
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
"%V_buffer_size %uz is not enough for cache key, "
- "it should increased at least to %uz",
+ "it should be increased to at least %uz",
&u->conf->module, u->conf->buffer_size,
ngx_align(r->cache->header_start + 256, 1024));
@@ -1096,7 +1096,7 @@ ngx_http_upstream_check_broken_connection(ngx_http_request_t *r,
if (getsockopt(c->fd, SOL_SOCKET, SO_ERROR, (void *) &err, &len)
== -1)
{
- err = ngx_errno;
+ err = ngx_socket_errno;
}
if (err) {
@@ -1977,7 +1977,7 @@ ngx_http_upstream_test_connect(ngx_connection_t *c)
if (getsockopt(c->fd, SOL_SOCKET, SO_ERROR, (void *) &err, &len)
== -1)
{
- err = ngx_errno;
+ err = ngx_socket_errno;
}
if (err) {
@@ -2557,7 +2557,9 @@ ngx_http_upstream_upgrade(ngx_http_request_t *r, ngx_http_upstream_t *u)
if (u->peer.connection->read->ready
|| u->buffer.pos != u->buffer.last)
{
+ ngx_post_event(c->read, &ngx_posted_events);
ngx_http_upstream_process_upgraded(r, 1, 1);
+ return;
}
ngx_http_upstream_process_upgraded(r, 0, 1);
diff --git a/src/os/unix/ngx_freebsd_sendfile_chain.c b/src/os/unix/ngx_freebsd_sendfile_chain.c
index b8665e042..11cec8226 100644
--- a/src/os/unix/ngx_freebsd_sendfile_chain.c
+++ b/src/os/unix/ngx_freebsd_sendfile_chain.c
@@ -231,7 +231,7 @@ ngx_freebsd_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit)
&& c->tcp_nopush == NGX_TCP_NOPUSH_UNSET)
{
if (ngx_tcp_nopush(c->fd) == NGX_ERROR) {
- err = ngx_errno;
+ err = ngx_socket_errno;
/*
* there is a tiny chance to be interrupted, however,
diff --git a/src/os/unix/ngx_linux_sendfile_chain.c b/src/os/unix/ngx_linux_sendfile_chain.c
index 431542d42..16395f943 100644
--- a/src/os/unix/ngx_linux_sendfile_chain.c
+++ b/src/os/unix/ngx_linux_sendfile_chain.c
@@ -163,7 +163,7 @@ ngx_linux_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit)
if (setsockopt(c->fd, IPPROTO_TCP, TCP_NODELAY,
(const void *) &tcp_nodelay, sizeof(int)) == -1)
{
- err = ngx_errno;
+ err = ngx_socket_errno;
/*
* there is a tiny chance to be interrupted, however,
@@ -189,7 +189,7 @@ ngx_linux_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit)
if (c->tcp_nodelay == NGX_TCP_NODELAY_UNSET) {
if (ngx_tcp_nopush(c->fd) == NGX_ERROR) {
- err = ngx_errno;
+ err = ngx_socket_errno;
/*
* there is a tiny chance to be interrupted, however,