@@ -351,6 +351,24 @@ static zend_string *php_stream_http_response_headers_parse(php_stream_wrapper *w
351351 return NULL ;
352352}
353353
354+ static inline void smart_str_append_header_value (smart_str * dest , const zend_string * value , const char * header_name )
355+ {
356+ const char * src = ZSTR_VAL (value );
357+ const char * cr = memchr (src , '\r' , ZSTR_LEN (value ));
358+ const char * lf = memchr (src , '\n' , ZSTR_LEN (value ));
359+ const char * nl = cr ;
360+ if (lf != NULL && (nl == NULL || lf < nl )) {
361+ nl = lf ;
362+ }
363+ if (nl != NULL ) {
364+ smart_str_appendl (dest , src , nl - src );
365+ php_error_docref (NULL , E_WARNING ,
366+ "Header %s value contains newline characters and has been truncated" , header_name );
367+ } else {
368+ smart_str_append (dest , value );
369+ }
370+ }
371+
354372static php_stream * php_stream_url_wrap_http_ex (php_stream_wrapper * wrapper ,
355373 const char * path , const char * mode , int options , zend_string * * opened_path ,
356374 php_stream_context * context , int redirect_max , int flags ,
@@ -361,7 +379,7 @@ static php_stream *php_stream_url_wrap_http_ex(php_stream_wrapper *wrapper,
361379 int use_ssl ;
362380 int use_proxy = 0 ;
363381 zend_string * tmp = NULL ;
364- char * ua_str = NULL ;
382+ zend_string * ua_str = NULL ;
365383 zval * ua_zval = NULL , * tmpzval = NULL , ssl_proxy_peer_name ;
366384 int reqok = 0 ;
367385 char * http_header_line = NULL ;
@@ -788,7 +806,7 @@ static php_stream *php_stream_url_wrap_http_ex(php_stream_wrapper *wrapper,
788806 /* if the user has configured who they are, send a From: line */
789807 if (!(have_header & HTTP_HEADER_FROM ) && FG (from_address )) {
790808 smart_str_appends (& req_buf , "From: " );
791- smart_str_appends (& req_buf , FG (from_address ));
809+ smart_str_append_header_value (& req_buf , FG (from_address ), "From" );
792810 smart_str_appends (& req_buf , "\r\n" );
793811 }
794812
@@ -817,30 +835,15 @@ static php_stream *php_stream_url_wrap_http_ex(php_stream_wrapper *wrapper,
817835 if (context &&
818836 (ua_zval = php_stream_context_get_option (context , "http" , "user_agent" )) != NULL &&
819837 Z_TYPE_P (ua_zval ) == IS_STRING ) {
820- ua_str = Z_STRVAL_P (ua_zval );
838+ ua_str = Z_STR_P (ua_zval );
821839 } else if (FG (user_agent )) {
822840 ua_str = FG (user_agent );
823841 }
824842
825- if (((have_header & HTTP_HEADER_USER_AGENT ) == 0 ) && ua_str ) {
826- #define _UA_HEADER "User-Agent: %s\r\n"
827- char * ua ;
828- size_t ua_len ;
829-
830- ua_len = sizeof (_UA_HEADER ) + strlen (ua_str );
831-
832- /* ensure the header is only sent if user_agent is not blank */
833- if (ua_len > sizeof (_UA_HEADER )) {
834- ua = emalloc (ua_len + 1 );
835- if ((ua_len = slprintf (ua , ua_len , _UA_HEADER , ua_str )) > 0 ) {
836- ua [ua_len ] = 0 ;
837- smart_str_appendl (& req_buf , ua , ua_len );
838- } else {
839- php_stream_wrapper_warn_nt (wrapper , context , options , InvalidHeader ,
840- "Cannot construct User-agent header" );
841- }
842- efree (ua );
843- }
843+ if (((have_header & HTTP_HEADER_USER_AGENT ) == 0 ) && ua_str && ZSTR_LEN (ua_str )) {
844+ smart_str_appends (& req_buf , "User-Agent: " );
845+ smart_str_append_header_value (& req_buf , ua_str , "User-Agent" );
846+ smart_str_appends (& req_buf , "\r\n" );
844847 }
845848
846849 if (user_headers ) {
0 commit comments