[nginx] HTTP/2: fix indirect reprioritization.

Valentin Bartenev vbart at nginx.com
Mon Oct 26 14:39:30 UTC 2015


details:   http://hg.nginx.org/nginx/rev/b6a665bf858a
branches:  
changeset: 6272:b6a665bf858a
user:      Piotr Sikora <piotrsikora at google.com>
date:      Thu Oct 01 20:25:55 2015 -0700
description:
HTTP/2: fix indirect reprioritization.

Previously, streams that were indirectly reprioritized (either because of
a new exclusive dependency on their parent or because of removal of their
parent from the dependency tree), didn't have their pointer to the parent
node updated.

This broke detection of circular dependencies and, as a result, nginx
worker would crash due to stack overflow whenever such dependency was
introduced.

Found with afl-fuzz.

Signed-off-by: Piotr Sikora <piotrsikora at google.com>

diffstat:

 src/http/v2/ngx_http_v2.c |  17 +++++++++++++----
 1 files changed, 13 insertions(+), 4 deletions(-)

diffs (53 lines):

diff -r 22ee99422329 -r b6a665bf858a src/http/v2/ngx_http_v2.c
--- a/src/http/v2/ngx_http_v2.c	Thu Oct 01 20:25:55 2015 -0700
+++ b/src/http/v2/ngx_http_v2.c	Thu Oct 01 20:25:55 2015 -0700
@@ -2914,11 +2914,14 @@ ngx_http_v2_get_closed_node(ngx_http_v2_
         weight += child->weight;
     }
 
+    parent = node->parent;
+
     for (q = ngx_queue_head(&node->children);
          q != ngx_queue_sentinel(&node->children);
          q = ngx_queue_next(q))
     {
         child = ngx_queue_data(q, ngx_http_v2_node_t, queue);
+        child->parent = parent;
         child->weight = node->weight * child->weight / weight;
 
         if (child->weight == 0) {
@@ -2926,8 +2929,6 @@ ngx_http_v2_get_closed_node(ngx_http_v2_
         }
     }
 
-    parent = node->parent;
-
     if (parent == NGX_HTTP_V2_ROOT) {
         node->rank = 0;
         node->rel_weight = 1.0;
@@ -3940,8 +3941,8 @@ static void
 ngx_http_v2_set_dependency(ngx_http_v2_connection_t *h2c,
     ngx_http_v2_node_t *node, ngx_uint_t depend, ngx_uint_t exclusive)
 {
-    ngx_queue_t         *children;
-    ngx_http_v2_node_t  *parent, *next;
+    ngx_queue_t         *children, *q;
+    ngx_http_v2_node_t  *parent, *child, *next;
 
     parent = depend ? ngx_http_v2_get_node_by_id(h2c, depend, 0) : NULL;
 
@@ -4003,6 +4004,14 @@ ngx_http_v2_set_dependency(ngx_http_v2_c
     }
 
     if (exclusive) {
+        for (q = ngx_queue_head(children);
+             q != ngx_queue_sentinel(children);
+             q = ngx_queue_next(q))
+        {
+            child = ngx_queue_data(q, ngx_http_v2_node_t, queue);
+            child->parent = node;
+        }
+
         ngx_queue_add(&node->children, children);
         ngx_queue_init(children);
     }



More information about the nginx-devel mailing list