[nginx] HTTP/2: fixed ngx_http_v2_push_stream() allocation error handling.

Ruslan Ermilov ru at nginx.com
Thu Feb 15 14:55:03 UTC 2018


details:   http://hg.nginx.org/nginx/rev/affeb6ef732c
branches:  
changeset: 7208:affeb6ef732c
user:      Ruslan Ermilov <ru at nginx.com>
date:      Thu Feb 15 17:51:37 2018 +0300
description:
HTTP/2: fixed ngx_http_v2_push_stream() allocation error handling.

In particular, if a stream object allocation failed, and a client sent
the PRIORITY frame for this stream, ngx_http_v2_set_dependency() could
dereference a null pointer while trying to re-parent a dependency node.

diffstat:

 src/http/v2/ngx_http_v2.c |  62 +++++++++++++++++++++++++++++++++++-----------
 1 files changed, 47 insertions(+), 15 deletions(-)

diffs (115 lines):

diff -r 3d2b0b02bd3d -r affeb6ef732c src/http/v2/ngx_http_v2.c
--- a/src/http/v2/ngx_http_v2.c	Thu Feb 15 17:51:32 2018 +0300
+++ b/src/http/v2/ngx_http_v2.c	Thu Feb 15 17:51:37 2018 +0300
@@ -2546,20 +2546,47 @@ ngx_http_v2_push_stream(ngx_http_v2_stre
 {
     ngx_int_t                     rc;
     ngx_str_t                     value;
+    ngx_pool_t                   *pool;
+    ngx_uint_t                    index;
     ngx_table_elt_t             **h;
     ngx_connection_t             *fc;
     ngx_http_request_t           *r;
     ngx_http_v2_node_t           *node;
     ngx_http_v2_stream_t         *stream;
+    ngx_http_v2_srv_conf_t       *h2scf;
     ngx_http_v2_connection_t     *h2c;
     ngx_http_v2_parse_header_t   *header;
 
     h2c = parent->connection;
 
+    pool = ngx_create_pool(1024, h2c->connection->log);
+    if (pool == NULL) {
+        goto rst_stream;
+    }
+
     node = ngx_http_v2_get_node_by_id(h2c, h2c->last_push, 1);
 
     if (node == NULL) {
-        return NULL;
+        ngx_destroy_pool(pool);
+        goto rst_stream;
+    }
+
+    stream = ngx_http_v2_create_stream(h2c, 1);
+    if (stream == NULL) {
+
+        if (node->parent == NULL) {
+            h2scf = ngx_http_get_module_srv_conf(h2c->http_connection->conf_ctx,
+                                                 ngx_http_v2_module);
+
+            index = ngx_http_v2_index(h2scf, h2c->last_push);
+            h2c->streams_index[index] = node->index;
+
+            ngx_queue_insert_tail(&h2c->closed, &node->reuse);
+            h2c->closed_nodes++;
+        }
+
+        ngx_destroy_pool(pool);
+        goto rst_stream;
     }
 
     if (node->parent) {
@@ -2567,15 +2594,7 @@ ngx_http_v2_push_stream(ngx_http_v2_stre
         h2c->closed_nodes--;
     }
 
-    stream = ngx_http_v2_create_stream(h2c, 1);
-    if (stream == NULL) {
-        return NULL;
-    }
-
-    stream->pool = ngx_create_pool(1024, h2c->connection->log);
-    if (stream->pool == NULL) {
-        return NULL;
-    }
+    stream->pool = pool;
 
     r = stream->request;
     fc = r->connection;
@@ -2608,9 +2627,9 @@ ngx_http_v2_push_stream(ngx_http_v2_stre
         r->schema_end = r->schema_start + 4;
     }
 
-    value.data = ngx_pstrdup(stream->pool, path);
+    value.data = ngx_pstrdup(pool, path);
     if (value.data == NULL) {
-        return NULL;
+        goto close;
     }
 
     value.len = path->len;
@@ -2631,9 +2650,9 @@ ngx_http_v2_push_stream(ngx_http_v2_stre
 
         value.len = (*h)->value.len;
 
-        value.data = ngx_pnalloc(stream->pool, value.len + 1);
+        value.data = ngx_pnalloc(pool, value.len + 1);
         if (value.data == NULL) {
-            return NULL;
+            goto close;
         }
 
         ngx_memcpy(value.data, (*h)->value.data, value.len);
@@ -2663,7 +2682,20 @@ error:
         return NULL;
     }
 
-    (void) ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_INTERNAL_ERROR);
+close:
+
+    ngx_http_v2_close_stream(stream, NGX_HTTP_INTERNAL_SERVER_ERROR);
+
+    return NULL;
+
+rst_stream:
+
+    if (ngx_http_v2_send_rst_stream(h2c, h2c->last_push,
+                                    NGX_HTTP_INTERNAL_SERVER_ERROR)
+        != NGX_OK)
+    {
+        h2c->connection->error = 1;
+    }
 
     return NULL;
 }


More information about the nginx-devel mailing list