Mercurial > hg > nginx
comparison src/http/v2/ngx_http_v2.c @ 9179:ea1f29c2010c
HTTP/2: fixed buffer management with HTTP/2 auto-detection.
As part of normal HTTP/2 processing, incomplete frames are saved in the
control state using a fixed size memcpy of NGX_HTTP_V2_STATE_BUFFER_SIZE.
For this matter, two state buffers are reserved in the HTTP/2 recv buffer.
As part of HTTP/2 auto-detection on plain TCP connections, initial data
is first read into a buffer specified by the client_header_buffer_size
directive that doesn't have state reservation. Previously, this made it
possible to over-read the buffer as part of saving the state.
The fix is to read the available buffer size rather than a fixed size.
Although memcpy of a fixed size can produce a better optimized code,
handling of incomplete frames isn't a common execution path, so it was
sacrificed for the sake of simplicity of the fix.
author | Sergey Kandaurov <pluknet@nginx.com> |
---|---|
date | Sat, 21 Oct 2023 18:48:24 +0400 |
parents | cdda286c0f1b |
children | cb1e214efe41 |
comparison
equal
deleted
inserted
replaced
9178:b74f891053c7 | 9179:ea1f29c2010c |
---|---|
384 } | 384 } |
385 | 385 |
386 h2mcf = ngx_http_get_module_main_conf(h2c->http_connection->conf_ctx, | 386 h2mcf = ngx_http_get_module_main_conf(h2c->http_connection->conf_ctx, |
387 ngx_http_v2_module); | 387 ngx_http_v2_module); |
388 | 388 |
389 available = h2mcf->recv_buffer_size - 2 * NGX_HTTP_V2_STATE_BUFFER_SIZE; | 389 available = h2mcf->recv_buffer_size - NGX_HTTP_V2_STATE_BUFFER_SIZE; |
390 | 390 |
391 do { | 391 do { |
392 p = h2mcf->recv_buffer; | 392 p = h2mcf->recv_buffer; |
393 | 393 end = ngx_cpymem(p, h2c->state.buffer, h2c->state.buffer_used); |
394 ngx_memcpy(p, h2c->state.buffer, NGX_HTTP_V2_STATE_BUFFER_SIZE); | |
395 end = p + h2c->state.buffer_used; | |
396 | 394 |
397 n = c->recv(c, end, available); | 395 n = c->recv(c, end, available); |
398 | 396 |
399 if (n == NGX_AGAIN) { | 397 if (n == NGX_AGAIN) { |
400 break; | 398 break; |
2590 "state buffer overflow: %uz bytes required", size); | 2588 "state buffer overflow: %uz bytes required", size); |
2591 | 2589 |
2592 return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_INTERNAL_ERROR); | 2590 return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_INTERNAL_ERROR); |
2593 } | 2591 } |
2594 | 2592 |
2595 ngx_memcpy(h2c->state.buffer, pos, NGX_HTTP_V2_STATE_BUFFER_SIZE); | 2593 ngx_memcpy(h2c->state.buffer, pos, size); |
2596 | 2594 |
2597 h2c->state.buffer_used = size; | 2595 h2c->state.buffer_used = size; |
2598 h2c->state.handler = handler; | 2596 h2c->state.handler = handler; |
2599 h2c->state.incomplete = 1; | 2597 h2c->state.incomplete = 1; |
2600 | 2598 |