aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authornaruse <naruse@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2012-05-23 13:09:26 +0000
committernaruse <naruse@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2012-05-23 13:09:26 +0000
commit3ba0abdb157b490644264c3bc45cb8fbc1e1f46b (patch)
tree80bce60b70dc3152f5697701a90d6cf690e0b004
parentb0dd250dc95ea0fae89c3201967039d582fbf156 (diff)
downloadruby-3ba0abdb157b490644264c3bc45cb8fbc1e1f46b.tar.gz
* lib/net/http/header.rb (Net::HTTPHeader#range): fix broken parser of
HTTP Range request. Old one can't parse invalid specs and multiple specs correctly. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@35764 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
-rw-r--r--ChangeLog6
-rw-r--r--lib/net/http/header.rb40
-rw-r--r--test/net/http/test_httpheader.rb27
3 files changed, 61 insertions, 12 deletions
diff --git a/ChangeLog b/ChangeLog
index 5401882223..f396fd0a91 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+Wed May 23 22:06:14 2012 NARUSE, Yui <naruse@ruby-lang.org>
+
+ * lib/net/http/header.rb (Net::HTTPHeader#range): fix broken parser of
+ HTTP Range request. Old one can't parse invalid specs and multiple
+ specs correctly.
+
Wed May 23 10:18:54 2012 NAKAMURA Usaku <usa@ruby-lang.org>
* win32/win32.c (finish_overlapped_socket, overlapped_socket_io):
diff --git a/lib/net/http/header.rb b/lib/net/http/header.rb
index ec77c8c958..7e46e04395 100644
--- a/lib/net/http/header.rb
+++ b/lib/net/http/header.rb
@@ -177,18 +177,44 @@ module Net::HTTPHeader
# HTTP header field, or +nil+ if there is no such header.
def range
return nil unless @header['range']
- self['Range'].split(/,/).map {|spec|
- m = /bytes\s*=\s*(\d+)?\s*-\s*(\d+)?/i.match(spec) or
- raise HTTPHeaderSyntaxError, "wrong Range: #{spec}"
+
+ value = self['Range']
+ # byte-range-set = *( "," OWS ) ( byte-range-spec / suffix-byte-range-spec )
+ # *( OWS "," [ OWS ( byte-range-spec / suffix-byte-range-spec ) ] )
+ # corrected collected ABNF
+ # http://tools.ietf.org/html/draft-ietf-httpbis-p5-range-19#section-5.4.1
+ # http://tools.ietf.org/html/draft-ietf-httpbis-p5-range-19#appendix-C
+ # http://tools.ietf.org/html/draft-ietf-httpbis-p1-messaging-19#section-3.2.5
+ unless /\Abytes=((?:,[ \t]*)*(?:\d+-\d*|-\d+)(?:[ \t]*,(?:[ \t]*\d+-\d*|-\d+)?)*)\z/ =~ value
+ raise Net::HTTPHeaderSyntaxError, "invalid syntax for byte-ranges-specifier: '#{value}'"
+ end
+
+ byte_range_set = $1
+ result = byte_range_set.split(/,/).map {|spec|
+ m = /(\d+)?\s*-\s*(\d+)?/i.match(spec) or
+ raise Net::HTTPHeaderSyntaxError, "invalid byte-range-spec: '#{spec}'"
d1 = m[1].to_i
d2 = m[2].to_i
- if m[1] and m[2] then d1..d2
- elsif m[1] then d1..-1
- elsif m[2] then -d2..-1
+ if m[1] and m[2]
+ if d1 > d2
+ raise Net::HTTPHeaderSyntaxError, "last-byte-pos MUST greater than or equal to first-byte-pos but '#{spec}'"
+ end
+ d1..d2
+ elsif m[1]
+ d1..-1
+ elsif m[2]
+ -d2..-1
else
- raise HTTPHeaderSyntaxError, 'range is not specified'
+ raise Net::HTTPHeaderSyntaxError, 'range is not specified'
end
}
+ # if result.empty?
+ # byte-range-set must include at least one byte-range-spec or suffix-byte-range-spec
+ # but above regexp already denies it.
+ if result.size == 1 && result[0].begin == 0 && result[0].end == -1
+ raise Net::HTTPHeaderSyntaxError, 'only one suffix-byte-range-spec with zero suffix-length'
+ end
+ result
end
# Sets the HTTP Range: header.
diff --git a/test/net/http/test_httpheader.rb b/test/net/http/test_httpheader.rb
index 379c9bd1ad..062387189d 100644
--- a/test/net/http/test_httpheader.rb
+++ b/test/net/http/test_httpheader.rb
@@ -156,15 +156,32 @@ class HTTPHeaderTest < Test::Unit::TestCase
end
def test_range
- try_range(1..5, '1-5')
- try_range(234..567, '234-567')
- try_range(-5..-1, '-5')
- try_range(1..-1, '1-')
+ try_range([1..5], '1-5')
+ try_invalid_range('5-1')
+ try_range([234..567], '234-567')
+ try_range([-5..-1], '-5')
+ try_invalid_range('-0')
+ try_range([1..-1], '1-')
+ try_range([0..0,-1..-1], '0-0,-1')
+ try_range([1..2, 3..4], '1-2,3-4')
+ try_range([1..2, 3..4], '1-2 , 3-4')
+ try_range([1..2, 1..4], '1-2,1-4')
+
+ try_invalid_range('invalid')
+ try_invalid_range(' 12-')
+ try_invalid_range('12- ')
+ try_invalid_range('123-abc')
+ try_invalid_range('abc-123')
end
def try_range(r, s)
@c['range'] = "bytes=#{s}"
- assert_equal r, Array(@c.range)[0]
+ assert_equal r, @c.range
+ end
+
+ def try_invalid_range(s)
+ @c['range'] = "bytes=#{s}"
+ assert_raise(Net::HTTPHeaderSyntaxError, s){ @c.range }
end
def test_range=