[nginx] Request body: body is now cleared on errors.
Maxim Dounin
mdounin at mdounin.ru
Sat Apr 27 15:56:47 UTC 2024
details: http://freenginx.org/hg/nginx/rev/81082b5521dd
branches:
changeset: 9259:81082b5521dd
user: Maxim Dounin <mdounin at mdounin.ru>
date: Sat Apr 27 18:21:38 2024 +0300
description:
Request body: body is now cleared on errors.
Previously, after errors the request body was left in a potentially
inconsistent state, with r->headers_in.content_length_n which might be
larger than buffers actually stored in r->request_body->bufs (or not
set at all, in case of HTTP/2 and HTTP/3). This can cause issues if
the request body is subsequently used during error_page handling, such
as when proxying.
Fix is to clear r->request_body->bufs if this happens, and set
r->headers_in.content_length_n to 0, much like it happens when
ngx_http_discard_request_body() is called when returning 413 from
ngx_http_core_find_config_phase() for requests with Content-Length.
diffstat:
src/http/ngx_http_request_body.c | 16 ++++++++++------
src/http/v2/ngx_http_v2.c | 11 +++++++++++
src/http/v3/ngx_http_v3_request.c | 4 ++++
3 files changed, 25 insertions(+), 6 deletions(-)
diffs (112 lines):
diff --git a/src/http/ngx_http_request_body.c b/src/http/ngx_http_request_body.c
--- a/src/http/ngx_http_request_body.c
+++ b/src/http/ngx_http_request_body.c
@@ -228,6 +228,11 @@ done:
}
if (rc >= NGX_HTTP_SPECIAL_RESPONSE) {
+
+ r->lingering_close = 1;
+ r->headers_in.content_length_n = 0;
+ r->request_body->bufs = NULL;
+
r->main->count--;
r->read_event_handler = ngx_http_block_reading;
}
@@ -298,6 +303,11 @@ ngx_http_read_client_request_body_handle
rc = ngx_http_do_read_client_request_body(r);
if (rc >= NGX_HTTP_SPECIAL_RESPONSE) {
+
+ r->lingering_close = 1;
+ r->headers_in.content_length_n = 0;
+ r->request_body->bufs = NULL;
+
r->read_event_handler = ngx_http_block_reading;
ngx_http_finalize_request(r, rc);
}
@@ -1161,8 +1171,6 @@ ngx_http_request_body_chunked_filter(ngx
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
"client sent too many chunk extensions");
- r->lingering_close = 1;
-
return NGX_HTTP_REQUEST_ENTITY_TOO_LARGE;
}
@@ -1176,8 +1184,6 @@ ngx_http_request_body_chunked_filter(ngx
r->headers_in.content_length_n,
rb->chunked->size);
- r->lingering_close = 1;
-
return NGX_HTTP_REQUEST_ENTITY_TOO_LARGE;
}
@@ -1276,8 +1282,6 @@ ngx_http_request_body_chunked_filter(ngx
"client sent too many chunk extensions "
"or trailer headers");
- r->lingering_close = 1;
-
return NGX_HTTP_REQUEST_ENTITY_TOO_LARGE;
}
diff --git a/src/http/v2/ngx_http_v2.c b/src/http/v2/ngx_http_v2.c
--- a/src/http/v2/ngx_http_v2.c
+++ b/src/http/v2/ngx_http_v2.c
@@ -1106,7 +1106,11 @@ ngx_http_v2_state_read_data(ngx_http_v2_
stream->in_closed, 0);
if (rc != NGX_OK && rc != NGX_AGAIN) {
+
stream->skip_data = 1;
+ r->headers_in.content_length_n = 0;
+ r->request_body->bufs = NULL;
+
ngx_http_finalize_request(r, rc);
}
@@ -3768,6 +3772,7 @@ ngx_http_v2_run_request(ngx_http_request
"client prematurely closed stream");
r->stream->skip_data = 1;
+ r->headers_in.content_length_n = 0;
ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
goto failed;
@@ -4199,7 +4204,11 @@ ngx_http_v2_read_client_request_body_han
rc = ngx_http_v2_process_request_body(r, NULL, 0, r->stream->in_closed, 1);
if (rc != NGX_OK && rc != NGX_AGAIN) {
+
r->stream->skip_data = 1;
+ r->headers_in.content_length_n = 0;
+ r->request_body->bufs = NULL;
+
ngx_http_finalize_request(r, rc);
return;
}
@@ -4262,6 +4271,8 @@ ngx_http_v2_read_client_request_body_han
error:
stream->skip_data = 1;
+ r->headers_in.content_length_n = 0;
+ r->request_body->bufs = NULL;
ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
return;
diff --git a/src/http/v3/ngx_http_v3_request.c b/src/http/v3/ngx_http_v3_request.c
--- a/src/http/v3/ngx_http_v3_request.c
+++ b/src/http/v3/ngx_http_v3_request.c
@@ -1291,6 +1291,10 @@ ngx_http_v3_read_client_request_body_han
rc = ngx_http_v3_do_read_client_request_body(r);
if (rc >= NGX_HTTP_SPECIAL_RESPONSE) {
+
+ r->headers_in.content_length_n = 0;
+ r->request_body->bufs = NULL;
+
ngx_http_finalize_request(r, rc);
}
}
More information about the nginx-devel
mailing list