@@ -315,27 +315,25 @@ static int uwsgi_response(request_rec *r, proxy_conn_rec *backend, proxy_server_
315315 apr_bucket_brigade * pass_bb = apr_brigade_create (r -> pool , c -> bucket_alloc );
316316
317317 len = ap_getline (buffer , sizeof (buffer ), rp , 1 );
318-
319318 if (len <= 0 ) {
320- // oops
319+ /* invalid or empty */
321320 return HTTP_INTERNAL_SERVER_ERROR ;
322321 }
323-
324322 backend -> worker -> s -> read += len ;
325-
326- if (len >= sizeof (buffer )- 1 ) {
327- // oops
323+ if ((apr_size_t )len >= sizeof (buffer )) {
324+ /* too long */
328325 return HTTP_INTERNAL_SERVER_ERROR ;
329326 }
327+
330328 /* Position of http status code */
331329 int status_start ;
332330 if (apr_date_checkmask (buffer , "HTTP/#.# ###*" )) {
333331 status_start = 9 ;
334332 } else if (apr_date_checkmask (buffer , "HTTP/# ###*" )) {
335333 status_start = 7 ;
336334 } else {
337- // oops
338- return HTTP_INTERNAL_SERVER_ERROR ;
335+ /* not HTTP */
336+ return HTTP_BAD_GATEWAY ;
339337 }
340338 int status_end = status_start + 3 ;
341339
@@ -354,17 +352,41 @@ static int uwsgi_response(request_rec *r, proxy_conn_rec *backend, proxy_server_
354352 }
355353 r -> status_line = apr_pstrdup (r -> pool , & buffer [status_start ]);
356354
357- // start parsing headers;
355+ /* parse headers */
358356 while ((len = ap_getline (buffer , sizeof (buffer ), rp , 1 )) > 0 ) {
357+ if ((apr_size_t )len >= sizeof (buffer )) {
358+ /* too long */
359+ len = -1 ;
360+ break ;
361+ }
359362 value = strchr (buffer , ':' );
360- // invalid header skip
361- if (!value ) continue ;
362- * value = '\0' ;
363- ++ value ;
363+ if (!value ) {
364+ /* invalid header */
365+ len = -1 ;
366+ break ;
367+ }
368+ * value ++ = '\0' ;
369+ if (* ap_scan_http_token (buffer )) {
370+ /* invalid name */
371+ len = -1 ;
372+ break ;
373+ }
364374 while (apr_isspace (* value )) ++ value ;
365375 for (end = & value [strlen (value )- 1 ]; end > value && apr_isspace (* end ); -- end ) * end = '\0' ;
376+ if (* ap_scan_http_field_content (value )) {
377+ /* invalid value */
378+ len = -1 ;
379+ break ;
380+ }
366381 apr_table_add (r -> headers_out , buffer , value );
367382 }
383+ if (len < 0 ) {
384+ /* Reset headers, but not to NULL because things below the chain expect
385+ * this to be non NULL e.g. the ap_content_length_filter.
386+ */
387+ r -> headers_out = apr_table_make (r -> pool , 1 );
388+ return HTTP_BAD_GATEWAY ;
389+ }
368390
369391 if ((buf = apr_table_get (r -> headers_out , "Content-Type" ))) {
370392 ap_set_content_type (r , apr_pstrdup (r -> pool , buf ));
0 commit comments