summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorPiotr Sikora <piotrsikora@google.com>2015-10-01 20:25:55 -0700
committerPiotr Sikora <piotrsikora@google.com>2015-10-01 20:25:55 -0700
commitde4f0eb26b394f49abcc215badba443d3ab7922e (patch)
tree26c996d67f3a367b97ecc4265a716db36fe47965
parent71a6b600c25639cc7452a817806d3bf40149bf95 (diff)
downloadnginx-de4f0eb26b394f49abcc215badba443d3ab7922e.tar.gz
nginx-de4f0eb26b394f49abcc215badba443d3ab7922e.tar.bz2
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@google.com>
-rw-r--r--src/http/v2/ngx_http_v2.c17
1 files changed, 13 insertions, 4 deletions
diff --git a/src/http/v2/ngx_http_v2.c b/src/http/v2/ngx_http_v2.c
index 6cca2b9a3..51cf65a88 100644
--- a/src/http/v2/ngx_http_v2.c
+++ b/src/http/v2/ngx_http_v2.c
@@ -2914,11 +2914,14 @@ ngx_http_v2_get_closed_node(ngx_http_v2_connection_t *h2c)
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_connection_t *h2c)
}
}
- 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_connection_t *h2c,
}
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);
}