Mercurial > hg > nginx
comparison src/http/v2/ngx_http_v2.c @ 6272:b6a665bf858a
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>
author | Piotr Sikora <piotrsikora@google.com> |
---|---|
date | Thu, 01 Oct 2015 20:25:55 -0700 |
parents | 22ee99422329 |
children | 60f916da7294 |
comparison
equal
deleted
inserted
replaced
6271:22ee99422329 | 6272:b6a665bf858a |
---|---|
2912 { | 2912 { |
2913 child = ngx_queue_data(q, ngx_http_v2_node_t, queue); | 2913 child = ngx_queue_data(q, ngx_http_v2_node_t, queue); |
2914 weight += child->weight; | 2914 weight += child->weight; |
2915 } | 2915 } |
2916 | 2916 |
2917 parent = node->parent; | |
2918 | |
2917 for (q = ngx_queue_head(&node->children); | 2919 for (q = ngx_queue_head(&node->children); |
2918 q != ngx_queue_sentinel(&node->children); | 2920 q != ngx_queue_sentinel(&node->children); |
2919 q = ngx_queue_next(q)) | 2921 q = ngx_queue_next(q)) |
2920 { | 2922 { |
2921 child = ngx_queue_data(q, ngx_http_v2_node_t, queue); | 2923 child = ngx_queue_data(q, ngx_http_v2_node_t, queue); |
2924 child->parent = parent; | |
2922 child->weight = node->weight * child->weight / weight; | 2925 child->weight = node->weight * child->weight / weight; |
2923 | 2926 |
2924 if (child->weight == 0) { | 2927 if (child->weight == 0) { |
2925 child->weight = 1; | 2928 child->weight = 1; |
2926 } | 2929 } |
2927 } | 2930 } |
2928 | |
2929 parent = node->parent; | |
2930 | 2931 |
2931 if (parent == NGX_HTTP_V2_ROOT) { | 2932 if (parent == NGX_HTTP_V2_ROOT) { |
2932 node->rank = 0; | 2933 node->rank = 0; |
2933 node->rel_weight = 1.0; | 2934 node->rel_weight = 1.0; |
2934 | 2935 |
3938 | 3939 |
3939 static void | 3940 static void |
3940 ngx_http_v2_set_dependency(ngx_http_v2_connection_t *h2c, | 3941 ngx_http_v2_set_dependency(ngx_http_v2_connection_t *h2c, |
3941 ngx_http_v2_node_t *node, ngx_uint_t depend, ngx_uint_t exclusive) | 3942 ngx_http_v2_node_t *node, ngx_uint_t depend, ngx_uint_t exclusive) |
3942 { | 3943 { |
3943 ngx_queue_t *children; | 3944 ngx_queue_t *children, *q; |
3944 ngx_http_v2_node_t *parent, *next; | 3945 ngx_http_v2_node_t *parent, *child, *next; |
3945 | 3946 |
3946 parent = depend ? ngx_http_v2_get_node_by_id(h2c, depend, 0) : NULL; | 3947 parent = depend ? ngx_http_v2_get_node_by_id(h2c, depend, 0) : NULL; |
3947 | 3948 |
3948 if (parent == NULL) { | 3949 if (parent == NULL) { |
3949 parent = NGX_HTTP_V2_ROOT; | 3950 parent = NGX_HTTP_V2_ROOT; |
4001 | 4002 |
4002 children = &parent->children; | 4003 children = &parent->children; |
4003 } | 4004 } |
4004 | 4005 |
4005 if (exclusive) { | 4006 if (exclusive) { |
4007 for (q = ngx_queue_head(children); | |
4008 q != ngx_queue_sentinel(children); | |
4009 q = ngx_queue_next(q)) | |
4010 { | |
4011 child = ngx_queue_data(q, ngx_http_v2_node_t, queue); | |
4012 child->parent = node; | |
4013 } | |
4014 | |
4006 ngx_queue_add(&node->children, children); | 4015 ngx_queue_add(&node->children, children); |
4007 ngx_queue_init(children); | 4016 ngx_queue_init(children); |
4008 } | 4017 } |
4009 | 4018 |
4010 if (node->parent != NULL) { | 4019 if (node->parent != NULL) { |