11// Licensed to the .NET Foundation under one or more agreements.
22// The .NET Foundation licenses this file to you under the MIT license.
33
4- using System ;
5- using System . Collections . Generic ;
6- using System . Net ;
7- using System . Net . Http ;
8-
94namespace System . Net . Http
105{
116 internal sealed class HttpEnvironmentProxyCredentials : ICredentials
@@ -115,10 +110,11 @@ private HttpEnvironmentProxy(Uri? httpProxy, Uri? httpsProxy, string? bypassList
115110 }
116111
117112 /// <summary>
118- /// This function will evaluate given string and it will try to convert
119- /// it to Uri object. The string could contain URI fragment, IP address and port
120- /// tuple or just IP address or name. It will return null if parsing fails .
113+ /// Attempt to parse a partial Uri string into a Uri object.
114+ /// The string may contain the scheme, user info, host, and port. The host is the only required part.
115+ /// Example expected inputs: contoso.com, contoso.com:8080, http://contoso.com/, [email protected] . 121116 /// </summary>
117+ /// <returns><see langword="null"/> if parsing fails.</returns>
122118 private static Uri ? GetUriFromString ( string ? value )
123119 {
124120 if ( string . IsNullOrEmpty ( value ) )
@@ -167,7 +163,7 @@ private HttpEnvironmentProxy(Uri? httpProxy, Uri? httpsProxy, string? bypassList
167163
168164 // Check if there is authentication part with user and possibly password.
169165 // Curl accepts raw text and that may break URI parser.
170- int separatorIndex = value . LastIndexOf ( '@' ) ;
166+ int separatorIndex = value . IndexOf ( '@' ) ;
171167 if ( separatorIndex != - 1 )
172168 {
173169 // The User and password may or may not be URL encoded.
@@ -187,6 +183,14 @@ private HttpEnvironmentProxy(Uri? httpProxy, Uri? httpsProxy, string? bypassList
187183 }
188184 }
189185
186+ // We expect inputs to not contain the path/query/fragment, but we do handle some simple cases like a trailing slash.
187+ // An arbitrary path can break this parsing logic, but we expect environment variables to be trusted and well formed.
188+ int delimiterIndex = value . IndexOfAny ( '/' , '?' , '#' ) ;
189+ if ( delimiterIndex >= 0 )
190+ {
191+ value = value . Substring ( 0 , delimiterIndex ) ;
192+ }
193+
190194 int ipV6AddressEnd = value . IndexOf ( ']' ) ;
191195 separatorIndex = value . LastIndexOf ( ':' ) ;
192196 // No ':' or it is part of IPv6 address.
@@ -197,18 +201,8 @@ private HttpEnvironmentProxy(Uri? httpProxy, Uri? httpsProxy, string? bypassList
197201 else
198202 {
199203 host = value . Substring ( 0 , separatorIndex ) ;
200- int endIndex = separatorIndex + 1 ;
201- // Strip any trailing characters after port number.
202- while ( endIndex < value . Length )
203- {
204- if ( ! char . IsDigit ( value [ endIndex ] ) )
205- {
206- break ;
207- }
208- endIndex += 1 ;
209- }
210204
211- if ( ! ushort . TryParse ( value . AsSpan ( separatorIndex + 1 , endIndex - separatorIndex - 1 ) , out port ) )
205+ if ( ! ushort . TryParse ( value . AsSpan ( separatorIndex + 1 ) , out port ) )
212206 {
213207 return null ;
214208 }
@@ -261,8 +255,7 @@ private bool IsMatchInBypassList(Uri input)
261255 {
262256 // This should match either domain it self or any subdomain or host
263257 // .foo.com will match foo.com it self or *.foo.com
264- if ( ( s . Length - 1 ) == input . Host . Length &&
265- string . Compare ( s , 1 , input . Host , 0 , input . Host . Length , StringComparison . OrdinalIgnoreCase ) == 0 )
258+ if ( s . AsSpan ( 1 ) . Equals ( input . Host , StringComparison . OrdinalIgnoreCase ) )
266259 {
267260 return true ;
268261 }
0 commit comments