Mercurial > hg > nginx
comparison src/http/v2/ngx_http_v2.c @ 7208:affeb6ef732c
HTTP/2: fixed ngx_http_v2_push_stream() allocation error handling.
In particular, if a stream object allocation failed, and a client sent
the PRIORITY frame for this stream, ngx_http_v2_set_dependency() could
dereference a null pointer while trying to re-parent a dependency node.
author | Ruslan Ermilov <ru@nginx.com> |
---|---|
date | Thu, 15 Feb 2018 17:51:37 +0300 |
parents | 3d2b0b02bd3d |
children | 3dfe9444324b |
comparison
equal
deleted
inserted
replaced
7207:3d2b0b02bd3d | 7208:affeb6ef732c |
---|---|
2544 ngx_http_v2_stream_t * | 2544 ngx_http_v2_stream_t * |
2545 ngx_http_v2_push_stream(ngx_http_v2_stream_t *parent, ngx_str_t *path) | 2545 ngx_http_v2_push_stream(ngx_http_v2_stream_t *parent, ngx_str_t *path) |
2546 { | 2546 { |
2547 ngx_int_t rc; | 2547 ngx_int_t rc; |
2548 ngx_str_t value; | 2548 ngx_str_t value; |
2549 ngx_pool_t *pool; | |
2550 ngx_uint_t index; | |
2549 ngx_table_elt_t **h; | 2551 ngx_table_elt_t **h; |
2550 ngx_connection_t *fc; | 2552 ngx_connection_t *fc; |
2551 ngx_http_request_t *r; | 2553 ngx_http_request_t *r; |
2552 ngx_http_v2_node_t *node; | 2554 ngx_http_v2_node_t *node; |
2553 ngx_http_v2_stream_t *stream; | 2555 ngx_http_v2_stream_t *stream; |
2556 ngx_http_v2_srv_conf_t *h2scf; | |
2554 ngx_http_v2_connection_t *h2c; | 2557 ngx_http_v2_connection_t *h2c; |
2555 ngx_http_v2_parse_header_t *header; | 2558 ngx_http_v2_parse_header_t *header; |
2556 | 2559 |
2557 h2c = parent->connection; | 2560 h2c = parent->connection; |
2558 | 2561 |
2562 pool = ngx_create_pool(1024, h2c->connection->log); | |
2563 if (pool == NULL) { | |
2564 goto rst_stream; | |
2565 } | |
2566 | |
2559 node = ngx_http_v2_get_node_by_id(h2c, h2c->last_push, 1); | 2567 node = ngx_http_v2_get_node_by_id(h2c, h2c->last_push, 1); |
2560 | 2568 |
2561 if (node == NULL) { | 2569 if (node == NULL) { |
2562 return NULL; | 2570 ngx_destroy_pool(pool); |
2571 goto rst_stream; | |
2572 } | |
2573 | |
2574 stream = ngx_http_v2_create_stream(h2c, 1); | |
2575 if (stream == NULL) { | |
2576 | |
2577 if (node->parent == NULL) { | |
2578 h2scf = ngx_http_get_module_srv_conf(h2c->http_connection->conf_ctx, | |
2579 ngx_http_v2_module); | |
2580 | |
2581 index = ngx_http_v2_index(h2scf, h2c->last_push); | |
2582 h2c->streams_index[index] = node->index; | |
2583 | |
2584 ngx_queue_insert_tail(&h2c->closed, &node->reuse); | |
2585 h2c->closed_nodes++; | |
2586 } | |
2587 | |
2588 ngx_destroy_pool(pool); | |
2589 goto rst_stream; | |
2563 } | 2590 } |
2564 | 2591 |
2565 if (node->parent) { | 2592 if (node->parent) { |
2566 ngx_queue_remove(&node->reuse); | 2593 ngx_queue_remove(&node->reuse); |
2567 h2c->closed_nodes--; | 2594 h2c->closed_nodes--; |
2568 } | 2595 } |
2569 | 2596 |
2570 stream = ngx_http_v2_create_stream(h2c, 1); | 2597 stream->pool = pool; |
2571 if (stream == NULL) { | |
2572 return NULL; | |
2573 } | |
2574 | |
2575 stream->pool = ngx_create_pool(1024, h2c->connection->log); | |
2576 if (stream->pool == NULL) { | |
2577 return NULL; | |
2578 } | |
2579 | 2598 |
2580 r = stream->request; | 2599 r = stream->request; |
2581 fc = r->connection; | 2600 fc = r->connection; |
2582 | 2601 |
2583 stream->in_closed = 1; | 2602 stream->in_closed = 1; |
2606 #endif | 2625 #endif |
2607 { | 2626 { |
2608 r->schema_end = r->schema_start + 4; | 2627 r->schema_end = r->schema_start + 4; |
2609 } | 2628 } |
2610 | 2629 |
2611 value.data = ngx_pstrdup(stream->pool, path); | 2630 value.data = ngx_pstrdup(pool, path); |
2612 if (value.data == NULL) { | 2631 if (value.data == NULL) { |
2613 return NULL; | 2632 goto close; |
2614 } | 2633 } |
2615 | 2634 |
2616 value.len = path->len; | 2635 value.len = path->len; |
2617 | 2636 |
2618 rc = ngx_http_v2_parse_path(r, &value); | 2637 rc = ngx_http_v2_parse_path(r, &value); |
2629 continue; | 2648 continue; |
2630 } | 2649 } |
2631 | 2650 |
2632 value.len = (*h)->value.len; | 2651 value.len = (*h)->value.len; |
2633 | 2652 |
2634 value.data = ngx_pnalloc(stream->pool, value.len + 1); | 2653 value.data = ngx_pnalloc(pool, value.len + 1); |
2635 if (value.data == NULL) { | 2654 if (value.data == NULL) { |
2636 return NULL; | 2655 goto close; |
2637 } | 2656 } |
2638 | 2657 |
2639 ngx_memcpy(value.data, (*h)->value.data, value.len); | 2658 ngx_memcpy(value.data, (*h)->value.data, value.len); |
2640 value.data[value.len] = '\0'; | 2659 value.data[value.len] = '\0'; |
2641 | 2660 |
2661 if (rc == NGX_DECLINED) { | 2680 if (rc == NGX_DECLINED) { |
2662 ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST); | 2681 ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST); |
2663 return NULL; | 2682 return NULL; |
2664 } | 2683 } |
2665 | 2684 |
2666 (void) ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_INTERNAL_ERROR); | 2685 close: |
2686 | |
2687 ngx_http_v2_close_stream(stream, NGX_HTTP_INTERNAL_SERVER_ERROR); | |
2688 | |
2689 return NULL; | |
2690 | |
2691 rst_stream: | |
2692 | |
2693 if (ngx_http_v2_send_rst_stream(h2c, h2c->last_push, | |
2694 NGX_HTTP_INTERNAL_SERVER_ERROR) | |
2695 != NGX_OK) | |
2696 { | |
2697 h2c->connection->error = 1; | |
2698 } | |
2667 | 2699 |
2668 return NULL; | 2700 return NULL; |
2669 } | 2701 } |
2670 | 2702 |
2671 | 2703 |