🕌

[Bug #21294] URI.extract で意図しない URI が抽出されるバグ報告

に公開

[Bug #21294] URI.extract is extracting invalid URIs with a mishmash of IPv6 notation with IPv4 address

require 'uri'

str = "
hoge
http://www.ruby-lang.org/
  http://www.ruby-lang.org/man-1.6/
  https://docs.ruby-lang.org/ja/latest/method/URI/s/extract.html
fuga
"

# URI にマッチした文字列を配列として返す
p URI.extract(str)
# => ["http://www.ruby-lang.org/", "http://www.ruby-lang.org/man-1.6/", "https://docs.ruby-lang.org/ja/latest/method/URI/s/extract.html"]

# http のみ抽出する
p URI.extract(str, :http)
# => ["http://www.ruby-lang.org/", "http://www.ruby-lang.org/man-1.6/"]

# https のみ抽出する
p URI.extract(str, :https)
# => ["https://docs.ruby-lang.org/ja/latest/method/URI/s/extract.html"]
  • この URI.extracthttp://[127.0.0.1] を渡すと URI として抽出されるので次のようなケースで意図せずエラーになってしまう
require 'uri'

URI.extract("Fake URL: http://[127.0.0.1]" , :http).each do |uri| # => ['http://[127.0.0.1]']
  URI.parse(uri) # => raise URI::InvalidURIError
end
$VERBOSE = true

require 'uri'

# warning: URI::RFC3986_PARSER.extract is obsolete. Use URI::RFC2396_PARSER.extract explicitly.
p URI.extract("Fake URL: http://[127.0.0.1]")
  • それでも同様のことをしたい場合は URI::RFC2396_PARSER.extractURI::RFC2396_PARSER.parse が利用できるみたいですね
    • URI::RFC2396_PARSER.parse であれば http://[127.0.0.1] も正しくパースできるみたい
    • ただし、この動作は古い RFC に基づいているので注意が必要とのこと
require 'uri'

URI::RFC2396_PARSER.extract("Fake URL: http://[127.0.0.1]" , :http).each do |uri| # => ['http://[127.0.0.1]']
  p URI::RFC2396_PARSER.parse(uri) # => #<URI::HTTP http://[127.0.0.1]>
end
GitHubで編集を提案

Discussion