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.
This commit is contained in:
Sergey Kandaurov 2017-04-20 18:26:37 +03:00
parent dbeb3679ae
commit a006d29b8a
8 changed files with 28 additions and 15 deletions

View file

@ -361,6 +361,8 @@ ngx_http_auth_basic_set_realm(ngx_http_request_t *r, ngx_str_t *realm)
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;
}

View file

@ -1080,6 +1080,7 @@ ngx_http_dav_location(ngx_http_request_t *r, u_char *path)
} else {
location = ngx_pnalloc(r->pool, r->uri.len);
if (location == NULL) {
ngx_http_clear_location(r);
return NGX_ERROR;
}

View file

@ -271,11 +271,6 @@ ngx_http_set_expires(ngx_http_request_t *r, ngx_http_headers_conf_t *conf)
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 @@ ngx_http_set_expires(ngx_http_request_t *r, ngx_http_headers_conf_t *conf)
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 @@ ngx_http_add_cache_control(ngx_http_request_t *r, ngx_http_header_val_t *hv,
}
}
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_http_add_cache_control(ngx_http_request_t *r, ngx_http_header_val_t *hv,
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;

View file

@ -425,6 +425,8 @@ ngx_http_range_singlepart_header(ngx_http_request_t *r,
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 @@ ngx_http_range_not_satisfiable(ngx_http_request_t *r)
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;
}

View file

@ -169,6 +169,7 @@ ngx_http_static_handler(ngx_http_request_t *r)
location = ngx_pnalloc(r->pool, len);
if (location == NULL) {
ngx_http_clear_location(r);
return NGX_HTTP_INTERNAL_SERVER_ERROR;
}

View file

@ -510,10 +510,12 @@ header_out(r, key, value)
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;
}

View file

@ -1002,6 +1002,7 @@ ngx_http_core_find_config_phase(ngx_http_request_t *r,
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;
}

View file

@ -4897,17 +4897,18 @@ ngx_http_upstream_copy_multi_header_lines(ngx_http_request_t *r,
}
}
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;