Merge branch 'nginx' (nginx-1.17.3).

Change-Id: Ibb51a80e6faa159d1259291d1638fd3d06eab7a9
Signed-off-by: Piotr Sikora <piotrsikora@google.com>
diff --git a/.hgtags b/.hgtags
index 7f2d14e..ec85611 100644
--- a/.hgtags
+++ b/.hgtags
@@ -441,3 +441,4 @@
 054c1c46395caff79bb4caf16f40b331f71bb6dd release-1.17.0
 7816bd7dabf6ee86c53c073b90a7143161546e06 release-1.17.1
 2fc9f853a6b7cd29dc84e0af2ed3cf78e0da6ca8 release-1.17.2
+ed4303aa1b31a9aad5440640c0840d9d0af45fed release-1.17.3
diff --git a/BUILD b/BUILD
index 6aa3098..10b0b42 100644
--- a/BUILD
+++ b/BUILD
@@ -1520,5 +1520,5 @@
     preinst = "@nginx_pkgoss//:debian_preinst",
     prerm = "@nginx_pkgoss//:debian_prerm",
     section = "httpd",
-    version = "1.17.2",
+    version = "1.17.3",
 )
diff --git a/build.bzl b/build.bzl
index 6019d63..76b5029 100644
--- a/build.bzl
+++ b/build.bzl
@@ -673,9 +673,9 @@
         name = "nginx_pkgoss",
         build_file_content = _PKGOSS_BUILD_FILE.format(nginx = nginx) +
                              _PKGOSS_BUILD_FILE_TAIL,
-        commit = "e76a000ffe16bb7f2abf2bcee40d88071c849dc2",  # nginx-1.17.2
+        commit = "f1d1a9fbc78c37a28de92df4e4cbed9268aa7304",  # nginx-1.17.3
         remote = "https://nginx.googlesource.com/nginx-pkgoss",
-        shallow_since = "1563882489 +0300",
+        shallow_since = "1565719153 +0300",
     )
 
 def nginx_repositories_zlib(bind):
diff --git a/docs/xml/nginx/changes.xml b/docs/xml/nginx/changes.xml
index 416de1f..492b469 100644
--- a/docs/xml/nginx/changes.xml
+++ b/docs/xml/nginx/changes.xml
@@ -5,6 +5,46 @@
 <change_log title="nginx">
 
 
+<changes ver="1.17.3" date="2019-08-13">
+
+<change type="security">
+<para lang="ru">
+при использовании HTTP/2 клиент мог вызвать
+чрезмерное потребление памяти и ресурсов процессора
+(CVE-2019-9511, CVE-2019-9513, CVE-2019-9516).
+</para>
+<para lang="en">
+when using HTTP/2 a client might cause
+excessive memory consumption and CPU usage
+(CVE-2019-9511, CVE-2019-9513, CVE-2019-9516).
+</para>
+</change>
+
+<change type="bugfix">
+<para lang="ru">
+при использовании сжатия в логах могли появляться сообщения "zero size buf";
+ошибка появилась в 1.17.2.
+</para>
+<para lang="en">
+"zero size buf" alerts might appear in logs when using gzipping;
+the bug had appeared in 1.17.2.
+</para>
+</change>
+
+<change type="bugfix">
+<para lang="ru">
+при использовании директивы resolver в SMTP прокси-сервере
+в рабочем процессе мог произойти segmentation fault.
+</para>
+<para lang="en">
+a segmentation fault might occur in a worker process
+if the "resolver" directive was used in SMTP proxy.
+</para>
+</change>
+
+</changes>
+
+
 <changes ver="1.17.2" date="2019-07-23">
 
 <change type="change">
diff --git a/src/core/nginx.h b/src/core/nginx.h
index 95589d5..3b0b837 100644
--- a/src/core/nginx.h
+++ b/src/core/nginx.h
@@ -13,8 +13,8 @@
 #define NGINX_NAME         "nginx"
 #endif
 
-#define nginx_version      1017002
-#define NGINX_VERSION      "1.17.2"
+#define nginx_version      1017003
+#define NGINX_VERSION      "1.17.3"
 #define NGINX_VER          NGINX_NAME "/" NGINX_VERSION
 
 #ifdef NGX_BUILD
diff --git a/src/http/modules/ngx_http_gzip_filter_module.c b/src/http/modules/ngx_http_gzip_filter_module.c
index 48f3dd7..c75169c 100644
--- a/src/http/modules/ngx_http_gzip_filter_module.c
+++ b/src/http/modules/ngx_http_gzip_filter_module.c
@@ -778,7 +778,7 @@
 
     ctx->out_buf->last = ctx->zstream.next_out;
 
-    if (ctx->zstream.avail_out == 0) {
+    if (ctx->zstream.avail_out == 0 && rc != Z_STREAM_END) {
 
         /* zlib wants to output some more gzipped data */
 
@@ -868,6 +868,7 @@
     ngx_http_gzip_ctx_t *ctx)
 {
     int           rc;
+    ngx_buf_t    *b;
     ngx_chain_t  *cl;
 
     ctx->zin = ctx->zstream.total_in;
@@ -888,13 +889,19 @@
         return NGX_ERROR;
     }
 
-    cl->buf = ctx->out_buf;
+    b = ctx->out_buf;
+
+    if (ngx_buf_size(b) == 0) {
+        b->temporary = 0;
+    }
+
+    b->last_buf = 1;
+
+    cl->buf = b;
     cl->next = NULL;
     *ctx->last_out = cl;
     ctx->last_out = &cl->next;
 
-    ctx->out_buf->last_buf = 1;
-
     ctx->zstream.avail_in = 0;
     ctx->zstream.avail_out = 0;
 
diff --git a/src/http/v2/ngx_http_v2.c b/src/http/v2/ngx_http_v2.c
index c070aa6..8d0d54f 100644
--- a/src/http/v2/ngx_http_v2.c
+++ b/src/http/v2/ngx_http_v2.c
@@ -274,6 +274,7 @@
     h2scf = ngx_http_get_module_srv_conf(hc->conf_ctx, ngx_http_v2_module);
 
     h2c->concurrent_pushes = h2scf->concurrent_pushes;
+    h2c->priority_limit = h2scf->concurrent_streams;
 
     h2c->pool = ngx_create_pool(h2scf->pool_size, h2c->connection->log);
     if (h2c->pool == NULL) {
@@ -1547,6 +1548,14 @@
         header->name.len = h2c->state.field_end - h2c->state.field_start;
         header->name.data = h2c->state.field_start;
 
+        if (header->name.len == 0) {
+            ngx_log_error(NGX_LOG_INFO, h2c->connection->log, 0,
+                          "client sent zero header name length");
+
+            return ngx_http_v2_connection_error(h2c,
+                                                NGX_HTTP_V2_PROTOCOL_ERROR);
+        }
+
         return ngx_http_v2_state_field_len(h2c, pos, end);
     }
 
@@ -1797,6 +1806,13 @@
         return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_SIZE_ERROR);
     }
 
+    if (--h2c->priority_limit == 0) {
+        ngx_log_error(NGX_LOG_INFO, h2c->connection->log, 0,
+                      "client sent too many PRIORITY frames");
+
+        return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_ENHANCE_YOUR_CALM);
+    }
+
     if (end - pos < NGX_HTTP_V2_PRIORITY_SIZE) {
         return ngx_http_v2_state_save(h2c, pos, end,
                                       ngx_http_v2_state_priority);
@@ -3155,6 +3171,8 @@
         h2c->processing++;
     }
 
+    h2c->priority_limit += h2scf->concurrent_streams;
+
     return stream;
 }
 
@@ -3292,10 +3310,6 @@
     ngx_uint_t                 i;
     ngx_http_core_srv_conf_t  *cscf;
 
-    if (header->name.len == 0) {
-        return NGX_ERROR;
-    }
-
     r->invalid_header = 0;
 
     cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
@@ -4414,6 +4428,8 @@
      */
     pool = stream->pool;
 
+    h2c->frames -= stream->frames;
+
     ngx_http_free_request(stream->request, rc);
 
     if (pool != h2c->state.pool) {
diff --git a/src/http/v2/ngx_http_v2.h b/src/http/v2/ngx_http_v2.h
index bec2216..69d55d1 100644
--- a/src/http/v2/ngx_http_v2.h
+++ b/src/http/v2/ngx_http_v2.h
@@ -122,6 +122,7 @@
     ngx_uint_t                       processing;
     ngx_uint_t                       frames;
     ngx_uint_t                       idle;
+    ngx_uint_t                       priority_limit;
 
     ngx_uint_t                       pushing;
     ngx_uint_t                       concurrent_pushes;
@@ -192,6 +193,8 @@
 
     ngx_buf_t                       *preread;
 
+    ngx_uint_t                       frames;
+
     ngx_http_v2_out_frame_t         *free_frames;
     ngx_chain_t                     *free_frame_headers;
     ngx_chain_t                     *free_bufs;
diff --git a/src/http/v2/ngx_http_v2_filter_module.c b/src/http/v2/ngx_http_v2_filter_module.c
index 3a3a31f..f1618ae 100644
--- a/src/http/v2/ngx_http_v2_filter_module.c
+++ b/src/http/v2/ngx_http_v2_filter_module.c
@@ -1678,22 +1678,34 @@
 ngx_http_v2_filter_get_data_frame(ngx_http_v2_stream_t *stream,
     size_t len, ngx_chain_t *first, ngx_chain_t *last)
 {
-    u_char                    flags;
-    ngx_buf_t                *buf;
-    ngx_chain_t              *cl;
-    ngx_http_v2_out_frame_t  *frame;
+    u_char                     flags;
+    ngx_buf_t                 *buf;
+    ngx_chain_t               *cl;
+    ngx_http_v2_out_frame_t   *frame;
+    ngx_http_v2_connection_t  *h2c;
 
     frame = stream->free_frames;
+    h2c = stream->connection;
 
     if (frame) {
         stream->free_frames = frame->next;
 
-    } else {
+    } else if (h2c->frames < 10000) {
         frame = ngx_palloc(stream->request->pool,
                            sizeof(ngx_http_v2_out_frame_t));
         if (frame == NULL) {
             return NULL;
         }
+
+        stream->frames++;
+        h2c->frames++;
+
+    } else {
+        ngx_log_error(NGX_LOG_INFO, h2c->connection->log, 0,
+                      "http2 flood detected");
+
+        h2c->connection->error = 1;
+        return NULL;
     }
 
     flags = last->buf->last_buf ? NGX_HTTP_V2_END_STREAM_FLAG : 0;
diff --git a/src/mail/ngx_mail_smtp_handler.c b/src/mail/ngx_mail_smtp_handler.c
index 939fb1a..f1017e0 100644
--- a/src/mail/ngx_mail_smtp_handler.c
+++ b/src/mail/ngx_mail_smtp_handler.c
@@ -15,6 +15,7 @@
 static void ngx_mail_smtp_resolve_addr_handler(ngx_resolver_ctx_t *ctx);
 static void ngx_mail_smtp_resolve_name(ngx_event_t *rev);
 static void ngx_mail_smtp_resolve_name_handler(ngx_resolver_ctx_t *ctx);
+static void ngx_mail_smtp_block_reading(ngx_event_t *rev);
 static void ngx_mail_smtp_greeting(ngx_mail_session_t *s, ngx_connection_t *c);
 static void ngx_mail_smtp_invalid_pipelining(ngx_event_t *rev);
 static ngx_int_t ngx_mail_smtp_create_buffer(ngx_mail_session_t *s,
@@ -88,6 +89,9 @@
     ctx->data = s;
     ctx->timeout = cscf->resolver_timeout;
 
+    s->resolver_ctx = ctx;
+    c->read->handler = ngx_mail_smtp_block_reading;
+
     if (ngx_resolve_addr(ctx) != NGX_OK) {
         ngx_mail_close_connection(c);
     }
@@ -169,6 +173,9 @@
     ctx->data = s;
     ctx->timeout = cscf->resolver_timeout;
 
+    s->resolver_ctx = ctx;
+    c->read->handler = ngx_mail_smtp_block_reading;
+
     if (ngx_resolve_name(ctx) != NGX_OK) {
         ngx_mail_close_connection(c);
     }
@@ -239,6 +246,38 @@
 
 
 static void
+ngx_mail_smtp_block_reading(ngx_event_t *rev)
+{
+    ngx_connection_t    *c;
+    ngx_mail_session_t  *s;
+    ngx_resolver_ctx_t  *ctx;
+
+    c = rev->data;
+    s = c->data;
+
+    ngx_log_debug0(NGX_LOG_DEBUG_MAIL, c->log, 0, "smtp reading blocked");
+
+    if (ngx_handle_read_event(rev, 0) != NGX_OK) {
+
+        if (s->resolver_ctx) {
+            ctx = s->resolver_ctx;
+
+            if (ctx->handler == ngx_mail_smtp_resolve_addr_handler) {
+                ngx_resolve_addr_done(ctx);
+
+            } else if (ctx->handler == ngx_mail_smtp_resolve_name_handler) {
+                ngx_resolve_name_done(ctx);
+            }
+
+            s->resolver_ctx = NULL;
+        }
+
+        ngx_mail_close_connection(c);
+    }
+}
+
+
+static void
 ngx_mail_smtp_greeting(ngx_mail_session_t *s, ngx_connection_t *c)
 {
     ngx_msec_t                 timeout;
@@ -258,6 +297,10 @@
         ngx_mail_close_connection(c);
     }
 
+    if (c->read->ready) {
+        ngx_post_event(c->read, &ngx_posted_events);
+    }
+
     if (sscf->greeting_delay) {
          c->read->handler = ngx_mail_smtp_invalid_pipelining;
          return;