Skip to content

Commit 5eeb414

Browse files
committed
Write $http_response_header to local var at end
Rather than trying to modify it mid-request. The protection against tampering that was used (addref) violates COW because an rc>1 array is being modified. Test bug69337.phpt changed because it was testing tampering with $http_response_header while the HTTP request is being executed. This simply no longer matters, so behavior is the same as if no tampering occurred.
1 parent 6cca4fc commit 5eeb414

File tree

2 files changed

+30
-32
lines changed

2 files changed

+30
-32
lines changed

ext/standard/http_fopen_wrapper.c

Lines changed: 27 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -107,9 +107,10 @@ static inline void strip_header(char *header_bag, char *lc_header_bag,
107107
}
108108
}
109109

110-
php_stream *php_stream_url_wrap_http_ex(php_stream_wrapper *wrapper,
110+
static php_stream *php_stream_url_wrap_http_ex(php_stream_wrapper *wrapper,
111111
const char *path, const char *mode, int options, zend_string **opened_path,
112-
php_stream_context *context, int redirect_max, int flags STREAMS_DC) /* {{{ */
112+
php_stream_context *context, int redirect_max, int flags,
113+
zval *response_header STREAMS_DC) /* {{{ */
113114
{
114115
php_stream *stream = NULL;
115116
php_url *resource = NULL;
@@ -119,7 +120,6 @@ php_stream *php_stream_url_wrap_http_ex(php_stream_wrapper *wrapper,
119120
char *ua_str = NULL;
120121
zval *ua_zval = NULL, *tmpzval = NULL, ssl_proxy_peer_name;
121122
char location[HTTP_HEADER_BLOCK_SIZE];
122-
zval response_header;
123123
int reqok = 0;
124124
char *http_header_line = NULL;
125125
char tmp_line[128];
@@ -137,11 +137,9 @@ php_stream *php_stream_url_wrap_http_ex(php_stream_wrapper *wrapper,
137137
zend_bool follow_location = 1;
138138
php_stream_filter *transfer_encoding = NULL;
139139
int response_code;
140-
zend_array *symbol_table;
141140
smart_str req_buf = {0};
142141
zend_bool custom_request_method;
143142

144-
ZVAL_UNDEF(&response_header);
145143
tmp_line[0] = '\0';
146144

147145
if (redirect_max < 1) {
@@ -659,22 +657,8 @@ php_stream *php_stream_url_wrap_http_ex(php_stream_wrapper *wrapper,
659657

660658
location[0] = '\0';
661659

662-
symbol_table = zend_rebuild_symbol_table();
663-
664-
if (header_init) {
665-
zval ztmp;
666-
array_init(&ztmp);
667-
zend_set_local_var_str("http_response_header", sizeof("http_response_header")-1, &ztmp, 0);
668-
}
669-
670-
{
671-
zval *response_header_ptr = zend_hash_str_find_ind(symbol_table, "http_response_header", sizeof("http_response_header")-1);
672-
if (!response_header_ptr || Z_TYPE_P(response_header_ptr) != IS_ARRAY) {
673-
ZVAL_UNDEF(&response_header);
674-
goto out;
675-
} else {
676-
ZVAL_COPY(&response_header, response_header_ptr);
677-
}
660+
if (Z_ISUNDEF_P(response_header)) {
661+
array_init(response_header);
678662
}
679663

680664
if (!php_stream_eof(stream)) {
@@ -741,7 +725,7 @@ php_stream *php_stream_url_wrap_http_ex(php_stream_wrapper *wrapper,
741725
}
742726
}
743727
ZVAL_STRINGL(&http_response, tmp_line, tmp_line_len);
744-
zend_hash_next_index_insert(Z_ARRVAL(response_header), &http_response);
728+
zend_hash_next_index_insert(Z_ARRVAL_P(response_header), &http_response);
745729
}
746730
} else {
747731
php_stream_wrapper_log_error(wrapper, options, "HTTP request failed, unexpected end of socket!");
@@ -840,7 +824,7 @@ php_stream *php_stream_url_wrap_http_ex(php_stream_wrapper *wrapper,
840824
{
841825
zval http_header;
842826
ZVAL_STRINGL(&http_header, http_header_line, http_header_line_length);
843-
zend_hash_next_index_insert(Z_ARRVAL(response_header), &http_header);
827+
zend_hash_next_index_insert(Z_ARRVAL_P(response_header), &http_header);
844828
}
845829
} else {
846830
break;
@@ -930,7 +914,9 @@ php_stream *php_stream_url_wrap_http_ex(php_stream_wrapper *wrapper,
930914
CHECK_FOR_CNTRL_CHARS(resource->pass)
931915
CHECK_FOR_CNTRL_CHARS(resource->path)
932916
}
933-
stream = php_stream_url_wrap_http_ex(wrapper, new_path, mode, options, opened_path, context, --redirect_max, HTTP_WRAPPER_REDIRECTED STREAMS_CC);
917+
stream = php_stream_url_wrap_http_ex(
918+
wrapper, new_path, mode, options, opened_path, context,
919+
--redirect_max, HTTP_WRAPPER_REDIRECTED, response_header STREAMS_CC);
934920
} else {
935921
php_stream_wrapper_log_error(wrapper, options, "HTTP request failed! %s", tmp_line);
936922
}
@@ -949,7 +935,7 @@ php_stream *php_stream_url_wrap_http_ex(php_stream_wrapper *wrapper,
949935

950936
if (stream) {
951937
if (header_init) {
952-
ZVAL_COPY(&stream->wrapperdata, &response_header);
938+
ZVAL_COPY(&stream->wrapperdata, response_header);
953939
}
954940
php_stream_notify_progress_init(context, 0, file_size);
955941

@@ -976,15 +962,28 @@ php_stream *php_stream_url_wrap_http_ex(php_stream_wrapper *wrapper,
976962
}
977963
}
978964

979-
zval_ptr_dtor(&response_header);
980-
981965
return stream;
982966
}
983967
/* }}} */
984968

985969
php_stream *php_stream_url_wrap_http(php_stream_wrapper *wrapper, const char *path, const char *mode, int options, zend_string **opened_path, php_stream_context *context STREAMS_DC) /* {{{ */
986970
{
987-
return php_stream_url_wrap_http_ex(wrapper, path, mode, options, opened_path, context, PHP_URL_REDIRECT_MAX, HTTP_WRAPPER_HEADER_INIT STREAMS_CC);
971+
php_stream *stream;
972+
zval headers;
973+
ZVAL_UNDEF(&headers);
974+
975+
stream = php_stream_url_wrap_http_ex(
976+
wrapper, path, mode, options, opened_path, context,
977+
PHP_URL_REDIRECT_MAX, HTTP_WRAPPER_HEADER_INIT, &headers STREAMS_CC);
978+
979+
if (!Z_ISUNDEF(headers)) {
980+
if (FAILURE == zend_set_local_var_str(
981+
"http_response_header", sizeof("http_response_header")-1, &headers, 0)) {
982+
zval_ptr_dtor(&headers);
983+
}
984+
}
985+
986+
return stream;
988987
}
989988
/* }}} */
990989

ext/standard/tests/http/bug69337.phpt

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,6 @@ var_dump($f);
3535
?>
3636
==DONE==
3737
--EXPECTF--
38-
string(26) "HTTP/1.0 404 Not Found
39-
40-
"
41-
==DONE==
38+
Warning: file_get_contents(http://127.0.0.1:22345/): failed to open stream: HTTP request failed! HTTP/1.0 404 Not Found%ain %s on line %d
39+
bool(false)
40+
==DONE==

0 commit comments

Comments
 (0)