File tree Expand file tree Collapse file tree 4 files changed +33
-2
lines changed Expand file tree Collapse file tree 4 files changed +33
-2
lines changed Original file line number Diff line number Diff line change @@ -35,7 +35,7 @@ pub fn parse(input: &BStr) -> Result<Url, parse::Error> {
35
35
InputScheme :: Url { protocol_end } if input[ ..protocol_end] . eq_ignore_ascii_case ( b"file" ) => {
36
36
parse:: file_url ( input, protocol_end)
37
37
}
38
- InputScheme :: Url { .. } => parse:: url ( input) ,
38
+ InputScheme :: Url { protocol_end } => parse:: url ( input, protocol_end ) ,
39
39
InputScheme :: Scp { colon } => parse:: scp ( input, colon) ,
40
40
}
41
41
}
Original file line number Diff line number Diff line change @@ -19,6 +19,9 @@ pub enum Error {
19
19
kind : UrlKind ,
20
20
source : url:: ParseError ,
21
21
} ,
22
+
23
+ #[ error( "The host portion of the following URL is too long ({} bytes, {len} bytes total): {truncated_url:?}" , truncated_url. len( ) ) ]
24
+ TooLong { truncated_url : BString , len : usize } ,
22
25
#[ error( "{} \" {url}\" does not specify a path to a repository" , kind. as_str( ) ) ]
23
26
MissingRepositoryPath { url : BString , kind : UrlKind } ,
24
27
#[ error( "URL {url:?} is relative which is not allowed in this context" ) ]
@@ -79,7 +82,17 @@ pub(crate) fn find_scheme(input: &BStr) -> InputScheme {
79
82
InputScheme :: Local
80
83
}
81
84
82
- pub ( crate ) fn url ( input : & BStr ) -> Result < crate :: Url , Error > {
85
+ pub ( crate ) fn url ( input : & BStr , protocol_end : usize ) -> Result < crate :: Url , Error > {
86
+ const MAX_LEN : usize = 1024 ;
87
+ let bytes_to_path = input[ protocol_end + "://" . len ( ) ..]
88
+ . find ( b"/" )
89
+ . unwrap_or ( input. len ( ) - protocol_end) ;
90
+ if bytes_to_path > MAX_LEN {
91
+ return Err ( Error :: TooLong {
92
+ truncated_url : input[ ..( protocol_end + "://" . len ( ) + MAX_LEN ) . min ( input. len ( ) ) ] . into ( ) ,
93
+ len : input. len ( ) ,
94
+ } ) ;
95
+ }
83
96
let ( input, url) = input_to_utf8_and_url ( input, UrlKind :: Url ) ?;
84
97
let scheme = url. scheme ( ) . into ( ) ;
85
98
Load Diff Large diffs are not rendered by default.
Original file line number Diff line number Diff line change 1
1
use bstr:: { BStr , ByteSlice } ;
2
2
use gix_url:: { testing:: TestUrlExtension , Scheme } ;
3
+ use std:: path:: Path ;
4
+ use std:: time:: Duration ;
3
5
4
6
fn assert_url ( url : & str , expected : gix_url:: Url ) -> Result < gix_url:: Url , crate :: Error > {
5
7
let actual = gix_url:: parse ( url. into ( ) ) ?;
@@ -134,3 +136,18 @@ mod unknown {
134
136
)
135
137
}
136
138
}
139
+
140
+ #[ test]
141
+ fn fuzzed ( ) {
142
+ let base = Path :: new ( "tests" ) . join ( "fixtures" ) . join ( "fuzzed" ) ;
143
+ let location = base. join ( Path :: new ( "very-long" ) . with_extension ( "url" ) ) ;
144
+ let url = std:: fs:: read ( & location) . unwrap ( ) ;
145
+ let start = std:: time:: Instant :: now ( ) ;
146
+ gix_url:: parse ( url. as_bstr ( ) ) . ok ( ) ;
147
+ assert ! (
148
+ start. elapsed( ) < Duration :: from_millis( 100 ) ,
149
+ "URL at '{}' parsed too slowly, took {:.00}s" ,
150
+ location. display( ) ,
151
+ start. elapsed( ) . as_secs_f32( )
152
+ )
153
+ }
You can’t perform that action at this time.
0 commit comments