@@ -7,6 +7,15 @@ export URI,
77
88import Base.==
99
10+ # Reject carriage return and line feed characters which can lead to CRLF injection
11+ const _CTL = Set ([' \r ' , ' \n ' ])
12+
13+ function _reject_ctl (s:: AbstractString , field:: Symbol )
14+ if any (c -> c in _CTL, s)
15+ throw (ArgumentError (" URI $field contains control characters; see RFC 3986 & RFC 9110" ))
16+ end
17+ end
18+
1019const DEBUG_LEVEL = Ref (0 )
1120include (" debug.jl" )
1221include (" parseutils.jl" )
@@ -82,6 +91,17 @@ function URI(uri::URI; scheme::AbstractString=uri.scheme,
8291 end
8392 querys = query isa AbstractString ? query : escapeuri (query)
8493
94+ # reject control characters in all components
95+ ! isabsent (scheme) && _reject_ctl (scheme, :scheme )
96+ ! isabsent (userinfo) && _reject_ctl (userinfo, :userinfo )
97+ ! isabsent (host) && _reject_ctl (host, :host )
98+ if port != = absent
99+ _reject_ctl (port, :port )
100+ end
101+ ! isabsent (path) && _reject_ctl (path, :path )
102+ ! isabsent (querys) && _reject_ctl (querys, :query )
103+ ! isabsent (fragment) && _reject_ctl (fragment, :fragment )
104+
85105 return URI (nostring, scheme, userinfo, host, port, path, querys, fragment)
86106end
87107
@@ -149,6 +169,12 @@ https://tools.ietf.org/html/rfc3986#section-4.1
149169"""
150170function parse_uri_reference (str:: Union{String, SubString{String}} ;
151171 strict = false )
172+ try
173+ _reject_ctl (str, :uri )
174+ catch e
175+ e isa ArgumentError && throw (ParseError (e. msg))
176+ rethrow ()
177+ end
152178 uri_reference_re = task_local_regex ()
153179 if ! exec (uri_reference_re, str)
154180 throw (ParseError (" URI contains invalid character" ))
0 commit comments