[#76442] [Ruby trunk Feature#11741] Migrate Ruby to Git from Subversion — naruse@...
Issue #11741 has been updated by Yui NARUSE.
3 messages
2016/07/19
[#76515] [Ruby trunk Bug#12610] webrick: protect from httpoxy — nagachika00@...
Issue #12610 has been updated by Tomoyuki Chikanaga.
3 messages
2016/07/22
[ruby-core:76281] [Ruby trunk Bug#12562] URI merge removes empty segment contrary to RFC 3986
From:
john.elrick@...
Date:
2016-07-06 20:37:40 UTC
List:
ruby-core #76281
Issue #12562 has been reported by John Elrick.
----------------------------------------
Bug #12562: URI merge removes empty segment contrary to RFC 3986
https://bugs.ruby-lang.org/issues/12562
* Author: John Elrick
* Status: Open
* Priority: Normal
* Assignee:
* ruby -v: 2.1.5+
* Backport: 2.1: UNKNOWN, 2.2: UNKNOWN, 2.3: UNKNOWN
----------------------------------------
## Background
This bug surfaced while testing against a server whose router expects an empty segment. The server routing is not correct, however, the result exposed the discontinuity compared to the specifications in RFC 3986.
## Description
~~~ ruby
URI.parse('https://www.example.com').merge('/foo//bar')
~~~
according to RFC 3986, this should result in:
~~~
https://www.example.com/foo//bar
~~~
However, the result of the operation is
~~~
https://www.example.com/foo/bar
~~~
The cause of the problem appears to be in `uri/generic.rb` at line 1080:
~~~ ruby
def split_path(path)
path.split(%r{/+}, -1)
end
~~~
The addition of the `+` operator causes the split to ignore the second solidus instead of reporting it as an empty segment. In normal operations, the extra solidus is ignored by the server, however, in this particular case the absence of the second solidus resulted in a 500 error.
## RFC 3986
Appendix B of RFC 3986 demonstrates the following Regular Expression ([RFC 3986 Page 51](https://tools.ietf.org/html/rfc3986#section-1.1.1)):
~~~
^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?
~~~
Processing this expression against the following demonstrates the differences between the spec and the operation of URI.split_path:
~~~
[1] pry(#<URI::HTTPS>)> path
=> "/foo//bar"
[2] pry(#<URI::HTTPS>)> path.split(%r{/+}, -1)
=> ["", "foo", "bar"]
[3] pry(#<URI::HTTPS>)> path
=> "/foo//bar"
[4] pry(#<URI::HTTPS>)> path.scan(%r{^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?})
=> [[nil, nil, nil, nil, "/foo//bar", nil, nil, nil, nil]]
[5] pry(#<URI::HTTPS>)> path = 'https://gollum:precious@www.hobbits.com/bilbo/baggins//frodo/baggins'
=> "https://gollum:precious@www.hobbits.com/bilbo/baggins//frodo/baggins"
[6] pry(#<URI::HTTPS>)> path.scan(%r{^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?})
=> [["https:", "https", "//gollum:precious@www.hobbits.com", "gollum:precious@www.hobbits.com", "/bilbo/baggins//frodo/baggins", nil, nil, nil, nil]]
~~~
In both cases, the double solidus is retained.
Additionally, the RFC ABNF syntax allows for an empty segment:
```
segment = *pchar
segment-nz = 1*pchar
segment-nz-nc = 1*( unreserved / pct-encoded / sub-delims / "@" )
; non-zero-length segment without any colon ":"
pchar = unreserved / pct-encoded / sub-delims / ":" / "@"
```
## Recommendation
Modify `uri/generic.rb` to read:
~~~ ruby
def split_path(path)
path.split(%r{/}, -1)
end
~~~
--
https://bugs.ruby-lang.org/
Unsubscribe: <mailto:ruby-core-request@ruby-lang.org?subject=unsubscribe>
<http://lists.ruby-lang.org/cgi-bin/mailman/options/ruby-core>