mirror of
https://github.com/nginx/nginx.git
synced 2025-02-25 18:55:26 -06:00
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.
This commit is contained in:
parent
2437532e7f
commit
89661c0e7d
@ -2546,20 +2546,47 @@ ngx_http_v2_push_stream(ngx_http_v2_stream_t *parent, ngx_str_t *path)
|
|||||||
{
|
{
|
||||||
ngx_int_t rc;
|
ngx_int_t rc;
|
||||||
ngx_str_t value;
|
ngx_str_t value;
|
||||||
|
ngx_pool_t *pool;
|
||||||
|
ngx_uint_t index;
|
||||||
ngx_table_elt_t **h;
|
ngx_table_elt_t **h;
|
||||||
ngx_connection_t *fc;
|
ngx_connection_t *fc;
|
||||||
ngx_http_request_t *r;
|
ngx_http_request_t *r;
|
||||||
ngx_http_v2_node_t *node;
|
ngx_http_v2_node_t *node;
|
||||||
ngx_http_v2_stream_t *stream;
|
ngx_http_v2_stream_t *stream;
|
||||||
|
ngx_http_v2_srv_conf_t *h2scf;
|
||||||
ngx_http_v2_connection_t *h2c;
|
ngx_http_v2_connection_t *h2c;
|
||||||
ngx_http_v2_parse_header_t *header;
|
ngx_http_v2_parse_header_t *header;
|
||||||
|
|
||||||
h2c = parent->connection;
|
h2c = parent->connection;
|
||||||
|
|
||||||
|
pool = ngx_create_pool(1024, h2c->connection->log);
|
||||||
|
if (pool == NULL) {
|
||||||
|
goto rst_stream;
|
||||||
|
}
|
||||||
|
|
||||||
node = ngx_http_v2_get_node_by_id(h2c, h2c->last_push, 1);
|
node = ngx_http_v2_get_node_by_id(h2c, h2c->last_push, 1);
|
||||||
|
|
||||||
if (node == NULL) {
|
if (node == NULL) {
|
||||||
return NULL;
|
ngx_destroy_pool(pool);
|
||||||
|
goto rst_stream;
|
||||||
|
}
|
||||||
|
|
||||||
|
stream = ngx_http_v2_create_stream(h2c, 1);
|
||||||
|
if (stream == NULL) {
|
||||||
|
|
||||||
|
if (node->parent == NULL) {
|
||||||
|
h2scf = ngx_http_get_module_srv_conf(h2c->http_connection->conf_ctx,
|
||||||
|
ngx_http_v2_module);
|
||||||
|
|
||||||
|
index = ngx_http_v2_index(h2scf, h2c->last_push);
|
||||||
|
h2c->streams_index[index] = node->index;
|
||||||
|
|
||||||
|
ngx_queue_insert_tail(&h2c->closed, &node->reuse);
|
||||||
|
h2c->closed_nodes++;
|
||||||
|
}
|
||||||
|
|
||||||
|
ngx_destroy_pool(pool);
|
||||||
|
goto rst_stream;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (node->parent) {
|
if (node->parent) {
|
||||||
@ -2567,15 +2594,7 @@ ngx_http_v2_push_stream(ngx_http_v2_stream_t *parent, ngx_str_t *path)
|
|||||||
h2c->closed_nodes--;
|
h2c->closed_nodes--;
|
||||||
}
|
}
|
||||||
|
|
||||||
stream = ngx_http_v2_create_stream(h2c, 1);
|
stream->pool = pool;
|
||||||
if (stream == NULL) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
stream->pool = ngx_create_pool(1024, h2c->connection->log);
|
|
||||||
if (stream->pool == NULL) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
r = stream->request;
|
r = stream->request;
|
||||||
fc = r->connection;
|
fc = r->connection;
|
||||||
@ -2608,9 +2627,9 @@ ngx_http_v2_push_stream(ngx_http_v2_stream_t *parent, ngx_str_t *path)
|
|||||||
r->schema_end = r->schema_start + 4;
|
r->schema_end = r->schema_start + 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
value.data = ngx_pstrdup(stream->pool, path);
|
value.data = ngx_pstrdup(pool, path);
|
||||||
if (value.data == NULL) {
|
if (value.data == NULL) {
|
||||||
return NULL;
|
goto close;
|
||||||
}
|
}
|
||||||
|
|
||||||
value.len = path->len;
|
value.len = path->len;
|
||||||
@ -2631,9 +2650,9 @@ ngx_http_v2_push_stream(ngx_http_v2_stream_t *parent, ngx_str_t *path)
|
|||||||
|
|
||||||
value.len = (*h)->value.len;
|
value.len = (*h)->value.len;
|
||||||
|
|
||||||
value.data = ngx_pnalloc(stream->pool, value.len + 1);
|
value.data = ngx_pnalloc(pool, value.len + 1);
|
||||||
if (value.data == NULL) {
|
if (value.data == NULL) {
|
||||||
return NULL;
|
goto close;
|
||||||
}
|
}
|
||||||
|
|
||||||
ngx_memcpy(value.data, (*h)->value.data, value.len);
|
ngx_memcpy(value.data, (*h)->value.data, value.len);
|
||||||
@ -2663,7 +2682,20 @@ error:
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
(void) ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_INTERNAL_ERROR);
|
close:
|
||||||
|
|
||||||
|
ngx_http_v2_close_stream(stream, NGX_HTTP_INTERNAL_SERVER_ERROR);
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
rst_stream:
|
||||||
|
|
||||||
|
if (ngx_http_v2_send_rst_stream(h2c, h2c->last_push,
|
||||||
|
NGX_HTTP_INTERNAL_SERVER_ERROR)
|
||||||
|
!= NGX_OK)
|
||||||
|
{
|
||||||
|
h2c->connection->error = 1;
|
||||||
|
}
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user