Mercurial > hg > nginx
comparison src/http/modules/ngx_http_grpc_module.c @ 7803:6df9d7df2784
gRPC: fixed handling of padding on DATA frames.
The response size check introduced in 39501ce97e29 did not take into
account possible padding on DATA frames, resulting in incorrect
"upstream sent response body larger than indicated content length" errors
if upstream server used padding in responses with known length.
Fix is to check the actual size of response buffers produced by the code,
similarly to how it is done in other protocols, instead of checking
the size of DATA frames.
Reported at:
http://mailman.nginx.org/pipermail/nginx-devel/2021-March/013907.html
author | Maxim Dounin <mdounin@mdounin.ru> |
---|---|
date | Tue, 23 Mar 2021 16:52:23 +0300 |
parents | 7ce28b4cc57e |
children | bdd4d89370a7 f5732fa038ad |
comparison
equal
deleted
inserted
replaced
7802:0215ec9aaa8a | 7803:6df9d7df2784 |
---|---|
2072 "for unknown stream %ui", | 2072 "for unknown stream %ui", |
2073 ctx->stream_id); | 2073 ctx->stream_id); |
2074 return NGX_ERROR; | 2074 return NGX_ERROR; |
2075 } | 2075 } |
2076 | 2076 |
2077 if (ctx->length != -1) { | |
2078 if ((off_t) ctx->rest > ctx->length) { | |
2079 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, | |
2080 "upstream sent response body larger " | |
2081 "than indicated content length"); | |
2082 return NGX_ERROR; | |
2083 } | |
2084 | |
2085 ctx->length -= ctx->rest; | |
2086 } | |
2087 | |
2088 if (ctx->rest > ctx->recv_window) { | 2077 if (ctx->rest > ctx->recv_window) { |
2089 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, | 2078 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, |
2090 "upstream violated stream flow control, " | 2079 "upstream violated stream flow control, " |
2091 "received %uz data frame with window %uz", | 2080 "received %uz data frame with window %uz", |
2092 ctx->rest, ctx->recv_window); | 2081 ctx->rest, ctx->recv_window); |
2448 | 2437 |
2449 ctx->rest -= b->last - b->pos; | 2438 ctx->rest -= b->last - b->pos; |
2450 b->pos = b->last; | 2439 b->pos = b->last; |
2451 buf->last = b->pos; | 2440 buf->last = b->pos; |
2452 | 2441 |
2442 if (ctx->length != -1) { | |
2443 | |
2444 if (buf->last - buf->pos > ctx->length) { | |
2445 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, | |
2446 "upstream sent response body larger " | |
2447 "than indicated content length"); | |
2448 return NGX_ERROR; | |
2449 } | |
2450 | |
2451 ctx->length -= buf->last - buf->pos; | |
2452 } | |
2453 | |
2453 return NGX_AGAIN; | 2454 return NGX_AGAIN; |
2454 } | 2455 } |
2455 | 2456 |
2456 b->pos += ctx->rest - ctx->padding; | 2457 b->pos += ctx->rest - ctx->padding; |
2457 buf->last = b->pos; | 2458 buf->last = b->pos; |
2458 ctx->rest = ctx->padding; | 2459 ctx->rest = ctx->padding; |
2460 | |
2461 if (ctx->length != -1) { | |
2462 | |
2463 if (buf->last - buf->pos > ctx->length) { | |
2464 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, | |
2465 "upstream sent response body larger " | |
2466 "than indicated content length"); | |
2467 return NGX_ERROR; | |
2468 } | |
2469 | |
2470 ctx->length -= buf->last - buf->pos; | |
2471 } | |
2459 | 2472 |
2460 done: | 2473 done: |
2461 | 2474 |
2462 if (ctx->padding) { | 2475 if (ctx->padding) { |
2463 ctx->state = ngx_http_grpc_st_padding; | 2476 ctx->state = ngx_http_grpc_st_padding; |