aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVladimir Khomutov <vl@wbsrv.ru>2023-11-29 11:13:05 +0300
committerVladimir Khomutov <vl@wbsrv.ru>2023-11-29 11:13:05 +0300
commitd8fa024ef1527a9aefbb52bedd70fa4449203488 (patch)
treecd869e8ed0a81fcde75383c274c40a89dc3ebf7f
parent0db94ba96a00ebfc4a3c55af8eaaf20f971a7c4c (diff)
downloadnginx-d8fa024ef1527a9aefbb52bedd70fa4449203488.tar.gz
nginx-d8fa024ef1527a9aefbb52bedd70fa4449203488.zip
HTTP: uniform checks in ngx_http_alloc_large_header_buffer().
If URI is not fully parsed yet, some pointers are not set. As a result, the calculation of "new + (ptr - old)" expression is flawed. According to C11, 6.5.6 Additive operators, p.9: : When two pointers are subtracted, both shall point to elements : of the same array object, or one past the last element of the : array object Since "ptr" is not set, subtraction leads to undefined behaviour, because "ptr" and "old" are not in the same buffer (i.e. array objects). Prodded by GCC undefined behaviour sanitizer.
-rw-r--r--src/http/ngx_http_request.c32
1 files changed, 25 insertions, 7 deletions
diff --git a/src/http/ngx_http_request.c b/src/http/ngx_http_request.c
index 058d50286..21738ff4c 100644
--- a/src/http/ngx_http_request.c
+++ b/src/http/ngx_http_request.c
@@ -1718,14 +1718,23 @@ ngx_http_alloc_large_header_buffer(ngx_http_request_t *r,
r->request_end = new + (r->request_end - old);
}
- r->method_end = new + (r->method_end - old);
+ if (r->method_end) {
+ r->method_end = new + (r->method_end - old);
+ }
+
+ if (r->uri_start) {
+ r->uri_start = new + (r->uri_start - old);
+ }
- r->uri_start = new + (r->uri_start - old);
- r->uri_end = new + (r->uri_end - old);
+ if (r->uri_end) {
+ r->uri_end = new + (r->uri_end - old);
+ }
if (r->schema_start) {
r->schema_start = new + (r->schema_start - old);
- r->schema_end = new + (r->schema_end - old);
+ if (r->schema_end) {
+ r->schema_end = new + (r->schema_end - old);
+ }
}
if (r->host_start) {
@@ -1749,9 +1758,18 @@ ngx_http_alloc_large_header_buffer(ngx_http_request_t *r,
} else {
r->header_name_start = new;
- r->header_name_end = new + (r->header_name_end - old);
- r->header_start = new + (r->header_start - old);
- r->header_end = new + (r->header_end - old);
+
+ if (r->header_name_end) {
+ r->header_name_end = new + (r->header_name_end - old);
+ }
+
+ if (r->header_start) {
+ r->header_start = new + (r->header_start - old);
+ }
+
+ if (r->header_end) {
+ r->header_end = new + (r->header_end - old);
+ }
}
r->header_in = b;