details: http://hg.nginx.org/nginx/rev/b6a665bf858a branches: changeset: 6272:b6a665bf858a user: Piotr Sikora <piotrsik...@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 <piotrsik...@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); } _______________________________________________ nginx-devel mailing list nginx-devel@nginx.org http://mailman.nginx.org/mailman/listinfo/nginx-devel