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) {