[nginx] HTTP: uniform checks in ngx_http_alloc_large_header_buffer().

Sergey Kandaurov pluknet at nginx.com
Mon Dec 11 13:51:26 UTC 2023


details:   https://hg.nginx.org/nginx/rev/b05c622715fa
branches:  
changeset: 9188:b05c622715fa
user:      Vladimir Khomutov <vl at wbsrv.ru>
date:      Wed Nov 29 11:13:05 2023 +0300
description:
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.

diffstat:

 src/http/ngx_http_request.c |  34 ++++++++++++++++++++++++++--------
 1 files changed, 26 insertions(+), 8 deletions(-)

diffs (54 lines):

diff -r dacad3a9c7b8 -r b05c622715fa src/http/ngx_http_request.c
--- a/src/http/ngx_http_request.c	Tue Nov 28 12:57:14 2023 +0300
+++ b/src/http/ngx_http_request.c	Wed Nov 29 11:13:05 2023 +0300
@@ -1718,14 +1718,23 @@ ngx_http_alloc_large_header_buffer(ngx_h
             r->request_end = new + (r->request_end - old);
         }
 
-        r->method_end = new + (r->method_end - old);
-
-        r->uri_start = new + (r->uri_start - old);
-        r->uri_end = new + (r->uri_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);
+        }
+
+        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_h
 
     } 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;


More information about the nginx-devel mailing list