Skip to content

Commit

Permalink
Require CRLF line endings in request line and headers
Browse files Browse the repository at this point in the history
Disallow bare CR, LF, NUL in header and request lines. Tighten
parsing of request lines to only allow single spaces, as specified
in the RFCs.

Forcing this RFC-compliant behavior breaks a lot of tests, so
fix the tests to correctly use CRLF instead of LF for requests
(other than the specific checks for handling of bad requests).

Fixes #137
  • Loading branch information
jeremyevans committed Jul 2, 2024
1 parent a27d7ed commit ee60354
Show file tree
Hide file tree
Showing 4 changed files with 133 additions and 32 deletions.
4 changes: 2 additions & 2 deletions lib/webrick/httprequest.rb
Original file line number Diff line number Diff line change
Expand Up @@ -458,7 +458,7 @@ def read_request_line(socket)
end

@request_time = Time.now
if /^(\S+)\s+(\S++)(?:\s+HTTP\/(\d+\.\d+))?\r?\n/mo =~ @request_line
if /^(\S+) (\S++)(?: HTTP\/(\d+\.\d+))?\r\n/mo =~ @request_line
@request_method = $1
@unparsed_uri = $2
@http_version = HTTPVersion.new($3 ? $3 : "0.9")
Expand All @@ -471,7 +471,7 @@ def read_request_line(socket)
def read_header(socket)
if socket
while line = read_line(socket)
break if /\A(#{CRLF}|#{LF})\z/om =~ line
break if /\A#{CRLF}\z/om =~ line
if (@request_bytes += line.bytesize) > MAX_HEADER_LENGTH
raise HTTPStatus::RequestEntityTooLarge, 'headers too large'
end
Expand Down
10 changes: 6 additions & 4 deletions lib/webrick/httputils.rb
Original file line number Diff line number Diff line change
Expand Up @@ -173,16 +173,18 @@ def parse_header(raw)
field = nil
raw.each_line{|line|
case line
when /^([A-Za-z0-9!\#$%&'*+\-.^_`|~]+):(.*?)\z/om
field, value = $1, $2.strip
when /^([A-Za-z0-9!\#$%&'*+\-.^_`|~]+):([^\r\n\0]*?)\r\n\z/om
field, value = $1, $2
field.downcase!
header[field] = HEADER_CLASSES[field].new unless header.has_key?(field)
header[field] << value
when /^\s+(.*?)/om
value = line.strip
when /^\s+([^\r\n\0]*?)\r\n/om
unless field
raise HTTPStatus::BadRequest, "bad header '#{line}'."
end
value = line
value.lstrip!
value.slice!(-2..-1)
header[field][-1] << " " << value
else
raise HTTPStatus::BadRequest, "bad header '#{line}'."
Expand Down
2 changes: 1 addition & 1 deletion test/webrick/test_filehandler.rb
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ def make_range_request(range_spec)
Range: #{range_spec}
END_OF_REQUEST
return StringIO.new(msg.gsub(/^ {6}/, ""))
return StringIO.new(msg.gsub(/^ {6}/, "").gsub("\n", "\r\n"))
end

def make_range_response(file, range_spec)
Expand Down
Loading

0 comments on commit ee60354

Please # to comment.