changeset 6986:0cdee26605f3

Cleaned up r->headers_out.headers allocation error handling. If initialization of a header failed for some reason after ngx_list_push(), leaving the header as is can result in uninitialized memory access by the header filter or the log module. The fix is to clear partially initialized headers in case of errors. For the Cache-Control header, the fix is to postpone pushing r->headers_out.cache_control until its value is completed.
author Sergey Kandaurov <pluknet@nginx.com>
date Thu, 20 Apr 2017 18:26:37 +0300
parents 23ecffd5bcfe
children 5116cfea1e9a
files src/http/modules/ngx_http_auth_basic_module.c src/http/modules/ngx_http_dav_module.c src/http/modules/ngx_http_headers_filter_module.c src/http/modules/ngx_http_range_filter_module.c src/http/modules/ngx_http_static_module.c src/http/modules/perl/nginx.xs src/http/ngx_http_core_module.c src/http/ngx_http_upstream.c
diffstat 8 files changed, 28 insertions(+), 15 deletions(-) [+]
line wrap: on
line diff
--- a/src/http/modules/ngx_http_auth_basic_module.c	Thu Apr 20 13:58:16 2017 +0300
+++ b/src/http/modules/ngx_http_auth_basic_module.c	Thu Apr 20 18:26:37 2017 +0300
@@ -361,6 +361,8 @@
 
     basic = ngx_pnalloc(r->pool, len);
     if (basic == NULL) {
+        r->headers_out.www_authenticate->hash = 0;
+        r->headers_out.www_authenticate = NULL;
         return NGX_HTTP_INTERNAL_SERVER_ERROR;
     }
 
--- a/src/http/modules/ngx_http_dav_module.c	Thu Apr 20 13:58:16 2017 +0300
+++ b/src/http/modules/ngx_http_dav_module.c	Thu Apr 20 18:26:37 2017 +0300
@@ -1080,6 +1080,7 @@
     } else {
         location = ngx_pnalloc(r->pool, r->uri.len);
         if (location == NULL) {
+            ngx_http_clear_location(r);
             return NGX_ERROR;
         }
 
--- a/src/http/modules/ngx_http_headers_filter_module.c	Thu Apr 20 13:58:16 2017 +0300
+++ b/src/http/modules/ngx_http_headers_filter_module.c	Thu Apr 20 18:26:37 2017 +0300
@@ -271,11 +271,6 @@
             return NGX_ERROR;
         }
 
-        ccp = ngx_array_push(&r->headers_out.cache_control);
-        if (ccp == NULL) {
-            return NGX_ERROR;
-        }
-
         cc = ngx_list_push(&r->headers_out.headers);
         if (cc == NULL) {
             return NGX_ERROR;
@@ -283,6 +278,12 @@
 
         cc->hash = 1;
         ngx_str_set(&cc->key, "Cache-Control");
+
+        ccp = ngx_array_push(&r->headers_out.cache_control);
+        if (ccp == NULL) {
+            return NGX_ERROR;
+        }
+
         *ccp = cc;
 
     } else {
@@ -470,11 +471,6 @@
         }
     }
 
-    ccp = ngx_array_push(&r->headers_out.cache_control);
-    if (ccp == NULL) {
-        return NGX_ERROR;
-    }
-
     cc = ngx_list_push(&r->headers_out.headers);
     if (cc == NULL) {
         return NGX_ERROR;
@@ -484,6 +480,11 @@
     ngx_str_set(&cc->key, "Cache-Control");
     cc->value = *value;
 
+    ccp = ngx_array_push(&r->headers_out.cache_control);
+    if (ccp == NULL) {
+        return NGX_ERROR;
+    }
+
     *ccp = cc;
 
     return NGX_OK;
--- a/src/http/modules/ngx_http_range_filter_module.c	Thu Apr 20 13:58:16 2017 +0300
+++ b/src/http/modules/ngx_http_range_filter_module.c	Thu Apr 20 18:26:37 2017 +0300
@@ -425,6 +425,8 @@
     content_range->value.data = ngx_pnalloc(r->pool,
                                     sizeof("bytes -/") - 1 + 3 * NGX_OFF_T_LEN);
     if (content_range->value.data == NULL) {
+        content_range->hash = 0;
+        r->headers_out.content_range = NULL;
         return NGX_ERROR;
     }
 
@@ -594,6 +596,8 @@
     content_range->value.data = ngx_pnalloc(r->pool,
                                        sizeof("bytes */") - 1 + NGX_OFF_T_LEN);
     if (content_range->value.data == NULL) {
+        content_range->hash = 0;
+        r->headers_out.content_range = NULL;
         return NGX_ERROR;
     }
 
--- a/src/http/modules/ngx_http_static_module.c	Thu Apr 20 13:58:16 2017 +0300
+++ b/src/http/modules/ngx_http_static_module.c	Thu Apr 20 18:26:37 2017 +0300
@@ -169,6 +169,7 @@
 
             location = ngx_pnalloc(r->pool, len);
             if (location == NULL) {
+                ngx_http_clear_location(r);
                 return NGX_HTTP_INTERNAL_SERVER_ERROR;
             }
 
--- a/src/http/modules/perl/nginx.xs	Thu Apr 20 13:58:16 2017 +0300
+++ b/src/http/modules/perl/nginx.xs	Thu Apr 20 18:26:37 2017 +0300
@@ -510,10 +510,12 @@
     header->hash = 1;
 
     if (ngx_http_perl_sv2str(aTHX_ r, &header->key, key) != NGX_OK) {
+        header->hash = 0;
         XSRETURN_EMPTY;
     }
 
     if (ngx_http_perl_sv2str(aTHX_ r, &header->value, value) != NGX_OK) {
+        header->hash = 0;
         XSRETURN_EMPTY;
     }
 
--- a/src/http/ngx_http_core_module.c	Thu Apr 20 13:58:16 2017 +0300
+++ b/src/http/ngx_http_core_module.c	Thu Apr 20 18:26:37 2017 +0300
@@ -1002,6 +1002,7 @@
             p = ngx_pnalloc(r->pool, len);
 
             if (p == NULL) {
+                ngx_http_clear_location(r);
                 ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
                 return NGX_OK;
             }
--- a/src/http/ngx_http_upstream.c	Thu Apr 20 13:58:16 2017 +0300
+++ b/src/http/ngx_http_upstream.c	Thu Apr 20 18:26:37 2017 +0300
@@ -4897,17 +4897,18 @@
         }
     }
 
-    ph = ngx_array_push(pa);
-    if (ph == NULL) {
-        return NGX_ERROR;
-    }
-
     ho = ngx_list_push(&r->headers_out.headers);
     if (ho == NULL) {
         return NGX_ERROR;
     }
 
     *ho = *h;
+
+    ph = ngx_array_push(pa);
+    if (ph == NULL) {
+        return NGX_ERROR;
+    }
+
     *ph = ho;
 
     return NGX_OK;