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;