瀏覽代碼

[http] Avoid using stack-allocated memory in http_step()

http_step() allocates a potentially large block of storage (since the
URI can be arbitrarily long), and can be invoked as part of an already
deep call stack via xfer_window_changed().

Signed-off-by: Michael Brown <mcb30@ipxe.org>
tags/v1.20.1
Michael Brown 12 年之前
父節點
當前提交
45e0327987
共有 1 個文件被更改,包括 32 次插入14 次删除
  1. 32
    14
      src/net/tcp/httpcore.c

+ 32
- 14
src/net/tcp/httpcore.c 查看文件

643
 	size_t user_pw_len = ( user ? ( strlen ( user ) + 1 /* ":" */ +
643
 	size_t user_pw_len = ( user ? ( strlen ( user ) + 1 /* ":" */ +
644
 					strlen ( password ) ) : 0 );
644
 					strlen ( password ) ) : 0 );
645
 	size_t user_pw_base64_len = base64_encoded_len ( user_pw_len );
645
 	size_t user_pw_base64_len = base64_encoded_len ( user_pw_len );
646
-	uint8_t user_pw[ user_pw_len + 1 /* NUL */ ];
647
-	char user_pw_base64[ user_pw_base64_len + 1 /* NUL */ ];
648
-	int rc;
649
 	int request_len = unparse_uri ( NULL, 0, http->uri,
646
 	int request_len = unparse_uri ( NULL, 0, http->uri,
650
 					URI_PATH_BIT | URI_QUERY_BIT );
647
 					URI_PATH_BIT | URI_QUERY_BIT );
651
-	char request[ request_len + 1 /* NUL */ ];
652
-	char range[48]; /* Enough for two 64-bit integers in decimal */
648
+	struct {
649
+		uint8_t user_pw[ user_pw_len + 1 /* NUL */ ];
650
+		char user_pw_base64[ user_pw_base64_len + 1 /* NUL */ ];
651
+		char request[ request_len + 1 /* NUL */ ];
652
+		char range[48]; /* Enough for two 64-bit integers in decimal */
653
+	} *dynamic;
653
 	int partial;
654
 	int partial;
655
+	int rc;
654
 
656
 
655
 	/* Do nothing if we have already transmitted the request */
657
 	/* Do nothing if we have already transmitted the request */
656
 	if ( ! ( http->flags & HTTP_TX_PENDING ) )
658
 	if ( ! ( http->flags & HTTP_TX_PENDING ) )
660
 	if ( ! xfer_window ( &http->socket ) )
662
 	if ( ! xfer_window ( &http->socket ) )
661
 		return;
663
 		return;
662
 
664
 
665
+	/* Allocate dynamic storage */
666
+	dynamic = malloc ( sizeof ( *dynamic ) );
667
+	if ( ! malloc ) {
668
+		rc = -ENOMEM;
669
+		goto err_alloc;
670
+	}
671
+
663
 	/* Construct path?query request */
672
 	/* Construct path?query request */
664
-	unparse_uri ( request, sizeof ( request ), http->uri,
673
+	unparse_uri ( dynamic->request, sizeof ( dynamic->request ), http->uri,
665
 		      URI_PATH_BIT | URI_QUERY_BIT );
674
 		      URI_PATH_BIT | URI_QUERY_BIT );
666
 
675
 
667
 	/* Construct authorisation, if applicable */
676
 	/* Construct authorisation, if applicable */
668
 	if ( user ) {
677
 	if ( user ) {
669
 		/* Make "user:password" string from decoded fields */
678
 		/* Make "user:password" string from decoded fields */
670
-		snprintf ( ( ( char * ) user_pw ), sizeof ( user_pw ),
671
-			   "%s:%s", user, password );
679
+		snprintf ( ( ( char * ) dynamic->user_pw ),
680
+			   sizeof ( dynamic->user_pw ), "%s:%s",
681
+			   user, password );
672
 
682
 
673
 		/* Base64-encode the "user:password" string */
683
 		/* Base64-encode the "user:password" string */
674
-		base64_encode ( user_pw, user_pw_len, user_pw_base64 );
684
+		base64_encode ( dynamic->user_pw, user_pw_len,
685
+				dynamic->user_pw_base64 );
675
 	}
686
 	}
676
 
687
 
677
 	/* Force a HEAD request if we have nowhere to send any received data */
688
 	/* Force a HEAD request if we have nowhere to send any received data */
682
 
693
 
683
 	/* Determine type of request */
694
 	/* Determine type of request */
684
 	partial = ( http->partial_len != 0 );
695
 	partial = ( http->partial_len != 0 );
685
-	snprintf ( range, sizeof ( range ), "%zd-%zd", http->partial_start,
696
+	snprintf ( dynamic->range, sizeof ( dynamic->range ),
697
+		   "%zd-%zd", http->partial_start,
686
 		   ( http->partial_start + http->partial_len - 1 ) );
698
 		   ( http->partial_start + http->partial_len - 1 ) );
687
 
699
 
688
 	/* Mark request as transmitted */
700
 	/* Mark request as transmitted */
698
 				  ( ( http->flags & HTTP_HEAD_ONLY ) ?
710
 				  ( ( http->flags & HTTP_HEAD_ONLY ) ?
699
 				    "HEAD" : "GET" ),
711
 				    "HEAD" : "GET" ),
700
 				  ( http->uri->path ? "" : "/" ),
712
 				  ( http->uri->path ? "" : "/" ),
701
-				  request, host,
713
+				  dynamic->request, host,
702
 				  ( http->uri->port ?
714
 				  ( http->uri->port ?
703
 				    ":" : "" ),
715
 				    ":" : "" ),
704
 				  ( http->uri->port ?
716
 				  ( http->uri->port ?
706
 				  ( ( http->flags & HTTP_KEEPALIVE ) ?
718
 				  ( ( http->flags & HTTP_KEEPALIVE ) ?
707
 				    "Connection: Keep-Alive\r\n" : "" ),
719
 				    "Connection: Keep-Alive\r\n" : "" ),
708
 				  ( partial ? "Range: bytes=" : "" ),
720
 				  ( partial ? "Range: bytes=" : "" ),
709
-				  ( partial ? range : "" ),
721
+				  ( partial ? dynamic->range : "" ),
710
 				  ( partial ? "\r\n" : "" ),
722
 				  ( partial ? "\r\n" : "" ),
711
 				  ( user ?
723
 				  ( user ?
712
 				    "Authorization: Basic " : "" ),
724
 				    "Authorization: Basic " : "" ),
713
-				  ( user ? user_pw_base64 : "" ),
725
+				  ( user ? dynamic->user_pw_base64 : "" ),
714
 				  ( user ? "\r\n" : "" ) ) ) != 0 ) {
726
 				  ( user ? "\r\n" : "" ) ) ) != 0 ) {
715
-		http_close ( http, rc );
727
+		goto err_xfer;
716
 	}
728
 	}
729
+
730
+ err_xfer:
731
+	free ( dynamic );
732
+ err_alloc:
733
+	if ( rc != 0 )
734
+		http_close ( http, rc );
717
 }
735
 }
718
 
736
 
719
 /**
737
 /**

Loading…
取消
儲存