@@ -659,7 +659,8 @@ apr_status_t h2_stream_set_request_rec(h2_stream *stream,
659659 if (stream -> rst_error ) {
660660 return APR_ECONNRESET ;
661661 }
662- status = h2_request_rcreate (& req , stream -> pool , r );
662+ status = h2_request_rcreate (& req , stream -> pool , r ,
663+ & stream -> session -> hd_scratch );
663664 if (status == APR_SUCCESS ) {
664665 ap_log_rerror (APLOG_MARK , APLOG_DEBUG , status , r ,
665666 H2_STRM_LOG (APLOGNO (03058 ), stream ,
@@ -691,13 +692,11 @@ static void set_error_response(h2_stream *stream, int http_status)
691692static apr_status_t add_trailer (h2_stream * stream ,
692693 const char * name , size_t nlen ,
693694 const char * value , size_t vlen ,
694- size_t max_field_len , int * pwas_added )
695+ h2_hd_scratch * scratch )
695696{
696697 conn_rec * c = stream -> session -> c1 ;
697- char * hname , * hvalue ;
698698 const char * existing ;
699699
700- * pwas_added = 0 ;
701700 if (nlen == 0 || name [0 ] == ':' ) {
702701 ap_log_cerror (APLOG_MARK , APLOG_DEBUG , APR_EINVAL , c ,
703702 H2_STRM_LOG (APLOGNO (03060 ), stream ,
@@ -710,20 +709,35 @@ static apr_status_t add_trailer(h2_stream *stream,
710709 if (!stream -> trailers_in ) {
711710 stream -> trailers_in = apr_table_make (stream -> pool , 5 );
712711 }
713- hname = apr_pstrndup (stream -> pool , name , nlen );
714- h2_util_camel_case_header (hname , nlen );
715- existing = apr_table_get (stream -> trailers_in , hname );
716- if (max_field_len
717- && ((existing ? strlen (existing )+ 2 : 0 ) + vlen + nlen + 2 > max_field_len )) {
718- /* "key: (oldval, )?nval" is too long */
712+
713+ if (((nlen + vlen + 2 ) > scratch -> max_len ))
719714 return APR_EINVAL ;
715+
716+ /* We need 0-terminated strings to operate on apr_table */
717+ AP_DEBUG_ASSERT (nlen < scratch -> max_len );
718+ memcpy (scratch -> name , name , nlen );
719+ scratch -> name [nlen ] = 0 ;
720+ AP_DEBUG_ASSERT (vlen < scratch -> max_len );
721+ memcpy (scratch -> value , value , vlen );
722+ scratch -> value [vlen ] = 0 ;
723+
724+ existing = apr_table_get (stream -> trailers_in , scratch -> name );
725+ if (existing ) {
726+ if (!vlen ) /* not adding a 0-length value to existing */
727+ return APR_SUCCESS ;
728+ if ((strlen (existing ) + 2 + vlen + nlen + 2 > scratch -> max_len )) {
729+ /* "name: existing, value" is too long */
730+ return APR_EINVAL ;
731+ }
732+ apr_table_merge (stream -> trailers_in , scratch -> name , scratch -> value );
720733 }
721- if (!existing ) * pwas_added = 1 ;
722- hvalue = apr_pstrndup (stream -> pool , value , vlen );
723- apr_table_mergen (stream -> trailers_in , hname , hvalue );
724- ap_log_cerror (APLOG_MARK , APLOG_TRACE2 , 0 , c ,
725- H2_STRM_MSG (stream , "added trailer '%s: %s'" ), hname , hvalue );
726-
734+ else {
735+ h2_util_camel_case_header (scratch -> name , nlen );
736+ apr_table_set (stream -> trailers_in , scratch -> name , scratch -> value );
737+ }
738+ ap_log_cerror (APLOG_MARK , APLOG_TRACE2 , 0 , c ,
739+ H2_STRM_MSG (stream , "added trailer '%s: %s'" ),
740+ scratch -> name , scratch -> value );
727741 return APR_SUCCESS ;
728742}
729743
@@ -732,7 +746,7 @@ apr_status_t h2_stream_add_header(h2_stream *stream,
732746 const char * value , size_t vlen )
733747{
734748 h2_session * session = stream -> session ;
735- int error = 0 , was_added = 0 ;
749+ int error = 0 ;
736750 apr_status_t status = APR_SUCCESS ;
737751
738752 H2_STRM_ASSERT_MAGIC (stream , H2_STRM_MAGIC_OK );
@@ -760,6 +774,7 @@ apr_status_t h2_stream_add_header(h2_stream *stream,
760774 ++ stream -> request_headers_added ;
761775 }
762776 else if (H2_SS_IDLE == stream -> state ) {
777+ int was_added ;
763778 if (!stream -> rtmp ) {
764779 if (H2_STREAM_CLIENT_INITIATED (stream -> id )) {
765780 ++ stream -> session -> remote .emitted_count ;
@@ -771,16 +786,16 @@ apr_status_t h2_stream_add_header(h2_stream *stream,
771786 }
772787 status = h2_request_add_header (stream -> rtmp , stream -> pool ,
773788 name , nlen , value , vlen ,
774- session -> s -> limit_req_fieldsize , & was_added );
789+ & session -> hd_scratch , & was_added );
775790 ap_log_cerror (APLOG_MARK , APLOG_TRACE2 , status , session -> c1 ,
776791 H2_STRM_MSG (stream , "add_header: '%.*s: %.*s" ),
777792 (int )nlen , name , (int )vlen , value );
778793 if (was_added ) ++ stream -> request_headers_added ;
779794 }
780795 else if (H2_SS_OPEN == stream -> state ) {
781796 status = add_trailer (stream , name , nlen , value , vlen ,
782- session -> s -> limit_req_fieldsize , & was_added );
783- if (was_added ) ++ stream -> request_headers_added ;
797+ & session -> hd_scratch );
798+ if (! status ) ++ stream -> request_headers_added ;
784799 }
785800 else {
786801 status = APR_EINVAL ;
@@ -789,16 +804,17 @@ apr_status_t h2_stream_add_header(h2_stream *stream,
789804
790805 if (APR_EINVAL == status ) {
791806 /* header too long */
792- if (!h2_stream_is_ready (stream )) {
807+ if (!h2_stream_is_ready (stream ) && ! stream -> request_headers_failed ) {
793808 ap_log_cerror (APLOG_MARK , APLOG_INFO , 0 , session -> c1 ,
794- H2_STRM_LOG (APLOGNO (10180 ), stream ,"Request header exceeds "
795- "LimitRequestFieldSize: %.*s" ),
809+ H2_STRM_LOG (APLOGNO (10180 ), stream ,
810+ "Request header exceeds LimitRequestFieldSize(%d): %.*s" ),
811+ (int )session -> hd_scratch .max_len ,
796812 (int )H2MIN (nlen , 80 ), name );
797813 }
798814 error = HTTP_REQUEST_HEADER_FIELDS_TOO_LARGE ;
799815 goto cleanup ;
800816 }
801-
817+
802818 if (session -> s -> limit_req_fields > 0
803819 && stream -> request_headers_added > session -> s -> limit_req_fields ) {
804820 /* too many header lines */
@@ -810,12 +826,13 @@ apr_status_t h2_stream_add_header(h2_stream *stream,
810826 if (!h2_stream_is_ready (stream )) {
811827 ap_log_cerror (APLOG_MARK , APLOG_INFO , 0 , session -> c1 ,
812828 H2_STRM_LOG (APLOGNO (10181 ), stream , "Number of request headers "
813- "exceeds LimitRequestFields" ));
829+ "exceeds LimitRequestFields(%d)" ),
830+ (int )session -> s -> limit_req_fields );
814831 }
815832 error = HTTP_REQUEST_HEADER_FIELDS_TOO_LARGE ;
816833 goto cleanup ;
817834 }
818-
835+
819836cleanup :
820837 if (error ) {
821838 ++ stream -> request_headers_failed ;
0 commit comments