diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/http/ngx_http_parse.c | 5 | ||||
| -rw-r--r-- | src/http/ngx_http_request_body.c | 30 | ||||
| -rw-r--r-- | src/http/v3/ngx_http_v3_request.c | 24 |
3 files changed, 35 insertions, 24 deletions
diff --git a/src/http/ngx_http_parse.c b/src/http/ngx_http_parse.c index a351f2b27..2015f56b2 100644 --- a/src/http/ngx_http_parse.c +++ b/src/http/ngx_http_parse.c @@ -2377,11 +2377,6 @@ ngx_http_parse_chunked(ngx_http_request_t *r, ngx_buf_t *b, } } - if (b->last_buf) { - /* XXX client prematurely closed connection */ - return NGX_ERROR; - } - data: ctx->state = state; diff --git a/src/http/ngx_http_request_body.c b/src/http/ngx_http_request_body.c index 7a9bbdd5d..a6dbcf502 100644 --- a/src/http/ngx_http_request_body.c +++ b/src/http/ngx_http_request_body.c @@ -960,6 +960,15 @@ ngx_http_request_body_length_filter(ngx_http_request_t *r, ngx_chain_t *in) break; } + size = cl->buf->last - cl->buf->pos; + + if (cl->buf->last_buf && (off_t) size < rb->rest) { + ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, + "client prematurely closed connection"); + r->connection->error = 1; + return NGX_HTTP_BAD_REQUEST; + } + tl = ngx_chain_get_free_buf(r->pool, &rb->free); if (tl == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; @@ -977,8 +986,6 @@ ngx_http_request_body_length_filter(ngx_http_request_t *r, ngx_chain_t *in) b->end = cl->buf->end; b->flush = r->request_body_no_buffering; - size = cl->buf->last - cl->buf->pos; - if ((off_t) size < rb->rest) { cl->buf->pos = cl->buf->last; rb->rest -= size; @@ -990,11 +997,6 @@ ngx_http_request_body_length_filter(ngx_http_request_t *r, ngx_chain_t *in) b->last_buf = 1; } - if (cl->buf->last_buf && rb->rest > 0) { - /* XXX client prematurely closed connection */ - return NGX_ERROR; - } - *ll = tl; ll = &tl->next; } @@ -1148,6 +1150,20 @@ ngx_http_request_body_chunked_filter(ngx_http_request_t *r, ngx_chain_t *in) continue; } + if (rc == NGX_AGAIN && cl->buf->last_buf) { + + /* last body buffer */ + + if (rb->chunked->length > 0) { + ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, + "client prematurely closed connection"); + r->connection->error = 1; + return NGX_HTTP_BAD_REQUEST; + } + + rc = NGX_DONE; + } + if (rc == NGX_DONE) { /* a whole response has been parsed successfully */ diff --git a/src/http/v3/ngx_http_v3_request.c b/src/http/v3/ngx_http_v3_request.c index 24ad771d6..fe3c79bf0 100644 --- a/src/http/v3/ngx_http_v3_request.c +++ b/src/http/v3/ngx_http_v3_request.c @@ -379,6 +379,10 @@ ngx_http_v3_parse_request_body(ngx_http_request_t *r, ngx_buf_t *b, ngx_int_t rc; ngx_connection_t *c; ngx_http_v3_parse_data_t *st; + enum { + sw_start = 0, + sw_skip + }; c = r->connection; st = ctx->h3_parse; @@ -395,12 +399,8 @@ ngx_http_v3_parse_request_body(ngx_http_request_t *r, ngx_buf_t *b, ctx->h3_parse = st; } - if (ctx->size) { - ctx->length = ctx->size + 1; - return (b->pos == b->last) ? NGX_AGAIN : NGX_OK; - } + while (b->pos < b->last && ctx->size == 0) { - while (b->pos < b->last) { rc = ngx_http_v3_parse_data(c, st, *b->pos++); if (rc > 0) { @@ -414,27 +414,27 @@ ngx_http_v3_parse_request_body(ngx_http_request_t *r, ngx_buf_t *b, } if (rc == NGX_AGAIN) { + ctx->state = sw_skip; continue; } /* rc == NGX_DONE */ ctx->size = st->length; - return NGX_OK; + ctx->state = sw_start; } - if (!b->last_buf) { + if (ctx->state == sw_skip) { ctx->length = 1; return NGX_AGAIN; } - if (st->state) { - goto failed; + if (b->pos == b->last) { + ctx->length = ctx->size; + return NGX_AGAIN; } - ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "http3 parse header done"); - - return NGX_DONE; + return NGX_OK; failed: |
