Skip to content
This repository was archived by the owner on Apr 10, 2025. It is now read-only.

Commit 85d0db2

Browse files
committed
IPRO: Copy the cache control value to ensure a correct lifetime
Fixes #1138
1 parent 8e25b58 commit 85d0db2

File tree

1 file changed

+20
-21
lines changed

1 file changed

+20
-21
lines changed

src/ngx_pagespeed.cc

Lines changed: 20 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -492,6 +492,10 @@ ngx_int_t copy_response_headers_to_ngx(
492492

493493
ngx_int_t i;
494494
for (i = 0 ; i < pagespeed_headers.NumAttributes() ; i++) {
495+
// For IPRO cache misses, these gs_ variables may point to freed memory
496+
// when nginx writes the headers to the output as the NgxBaseFetch instance
497+
// that owns this memory gets released during request processing. So we
498+
// copy these strings later on.
495499
const GoogleString& name_gs = pagespeed_headers.Name(i);
496500
const GoogleString& value_gs = pagespeed_headers.Value(i);
497501

@@ -512,6 +516,9 @@ ngx_int_t copy_response_headers_to_ngx(
512516
} // else we don't preserve any headers.
513517

514518
ngx_str_t name, value;
519+
value.len = value_gs.size();
520+
value.data = reinterpret_cast<u_char*>(
521+
string_piece_to_pool_string(r->pool, value_gs.c_str()));
515522

516523
// To prevent the gzip module from clearing weak etags, we output them
517524
// using a different name here. The etag header filter module runs behind
@@ -522,11 +529,15 @@ ngx_int_t copy_response_headers_to_ngx(
522529
name.data = reinterpret_cast<u_char*>(
523530
const_cast<char*>(kInternalEtagName));
524531
} else {
525-
name.len = name_gs.length();
526-
name.data = reinterpret_cast<u_char*>(const_cast<char*>(name_gs.data()));
532+
name.len = name_gs.size();
533+
name.data = reinterpret_cast<u_char*>(
534+
string_piece_to_pool_string(r->pool, name_gs.c_str()));
535+
}
536+
537+
// In case string_piece_to_pool_string failed:
538+
if (name.data == NULL || value.data == NULL) {
539+
return NGX_ERROR;
527540
}
528-
value.len = value_gs.length();
529-
value.data = reinterpret_cast<u_char*>(const_cast<char*>(value_gs.data()));
530541

531542
// TODO(jefftk): If we're setting a cache control header we'd like to
532543
// prevent any downstream code from changing it. Specifically, if we're
@@ -537,24 +548,17 @@ ngx_int_t copy_response_headers_to_ngx(
537548
// net/instaweb/apache/header_util:AddResponseHeadersToRequest
538549

539550
// Make copies of name and value to put into headers_out.
540-
541-
u_char* value_s = ngx_pstrdup(r->pool, &value);
542-
if (value_s == NULL) {
543-
return NGX_ERROR;
544-
}
545-
546551
if (STR_EQ_LITERAL(name, "Cache-Control")) {
547-
ps_set_cache_control(r, const_cast<char*>(value_gs.c_str()));
552+
ps_set_cache_control(r, reinterpret_cast<char*>(value.data));
548553
continue;
549554
} else if (STR_EQ_LITERAL(name, "Content-Type")) {
550555
// Unlike all the other headers, content_type is just a string.
551-
headers_out->content_type.data = value_s;
552-
headers_out->content_type.len = value.len;
556+
headers_out->content_type = value;
553557

554558
// We should not include the charset when determining content_type_len, so
555559
// scan for the ';' that marks the start of the charset part.
556560
for (ngx_uint_t i = 0; i < value.len; i++) {
557-
if (value_s[i] == ';') {
561+
if (value.data[i] == ';') {
558562
break;
559563
}
560564
headers_out->content_type_len = i + 1;
@@ -574,22 +578,17 @@ ngx_int_t copy_response_headers_to_ngx(
574578
continue;
575579
}
576580

577-
u_char* name_s = ngx_pstrdup(r->pool, &name);
578-
if (name_s == NULL) {
579-
return NGX_ERROR;
580-
}
581-
582581
ngx_table_elt_t* header = static_cast<ngx_table_elt_t*>(
583582
ngx_list_push(&headers_out->headers));
584583
if (header == NULL) {
585584
return NGX_ERROR;
586585
}
587586

588587
header->hash = 1; // Include this header in the output.
588+
header->key.data = name.data;
589589
header->key.len = name.len;
590-
header->key.data = name_s;
590+
header->value.data = value.data;
591591
header->value.len = value.len;
592-
header->value.data = value_s;
593592

594593
// Populate the shortcuts to commonly used headers.
595594
if (STR_EQ_LITERAL(name, "Date")) {

0 commit comments

Comments
 (0)