diff options
author | Kasumi Hanazuki <kasumi@rollingapple.net> | 2023-11-27 04:15:48 +0000 |
---|---|---|
committer | Hiroshi SHIBATA <hsbt@ruby-lang.org> | 2023-12-25 21:12:49 +0900 |
commit | eb53131367d6e1d3da16b0cd6bc44284ea3589ea (patch) | |
tree | 1b969044254962728adbaa1fcc08f92f16b83170 | |
parent | ea5776e7e4262c915f7f8b8884af420dd87d769c (diff) |
[ruby/ipaddr] ntop: Measure address size in bytes
`IPAddr.ntop` takes the binary representation of an IP address, whose
length should be 4 or 16 *bytes* (not characters/codepoints).
The current implementation accepts strings in any encoding, but for
some values in non-BINARY encoding, it fails proper length check and
raises an `AddressFamilyError`. Since passing strings in a multibyte
encoding has never worked correctly for years, this patch makes it an
explicit error with an `InvalidAddressError`.
Fixes: https://github.com/ruby/ipaddr/issues/56
https://github.com/ruby/ipaddr/commit/a33fd14d4a
-rw-r--r-- | lib/ipaddr.rb | 7 | ||||
-rw-r--r-- | test/test_ipaddr.rb | 29 |
2 files changed, 30 insertions, 6 deletions
diff --git a/lib/ipaddr.rb b/lib/ipaddr.rb index 03e1c18baa..07ef67a942 100644 --- a/lib/ipaddr.rb +++ b/lib/ipaddr.rb @@ -110,8 +110,13 @@ class IPAddr # Convert a network byte ordered string form of an IP address into # human readable form. + # It expects the string to be encoded in Encoding::ASCII_8BIT (BINARY). def self.ntop(addr) - case addr.size + if addr.is_a?(String) && addr.encoding != Encoding::BINARY + raise InvalidAddressError, "invalid encoding (given #{addr.encoding}, expected BINARY)" + end + + case addr.bytesize when 4 addr.unpack('C4').join('.') when 16 diff --git a/test/test_ipaddr.rb b/test/test_ipaddr.rb index 90a7fc352a..21843a04e7 100644 --- a/test/test_ipaddr.rb +++ b/test/test_ipaddr.rb @@ -133,18 +133,37 @@ class TC_IPAddr < Test::Unit::TestCase def test_ntop # IPv4 - assert_equal("192.168.1.1", IPAddr.ntop("\xC0\xA8\x01\x01")) + assert_equal("192.168.1.1", IPAddr.ntop("\xC0\xA8\x01\x01".b)) + assert_equal("10.231.140.171", IPAddr.ntop("\x0A\xE7\x8C\xAB".b)) # IPv6 assert_equal("0000:0000:0000:0000:0000:0000:0000:0001", - IPAddr.ntop("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01")) + IPAddr.ntop("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01".b)) + assert_equal("fe80:0000:0000:0000:f09f:9985:f09f:9986", + IPAddr.ntop("\xFE\x80\x00\x00\x00\x00\x00\x00\xF0\x9F\x99\x85\xF0\x9F\x99\x86".b)) # Invalid parameters + ## wrong length assert_raise(IPAddr::AddressFamilyError) { - IPAddr.ntop("192.168.1.1") + IPAddr.ntop("192.168.1.1".b) } - assert_raise(IPAddr::AddressFamilyError) { - IPAddr.ntop("\xC0\xA8\x01\xFF1") + IPAddr.ntop("\xC0\xA8\x01\xFF1".b) + } + ## UTF-8 + assert_raise(IPAddr::InvalidAddressError) { + IPAddr.ntop("192.168.1.1") + } + assert_raise(IPAddr::InvalidAddressError) { + IPAddr.ntop("\x0A\x0A\x0A\x0A") + } + assert_raise(IPAddr::InvalidAddressError) { + IPAddr.ntop("\x0A\xE7\x8C\xAB") + } + assert_raise(IPAddr::InvalidAddressError) { + IPAddr.ntop("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01") + } + assert_raise(IPAddr::InvalidAddressError) { + IPAddr.ntop("\xFE\x80\x00\x00\x00\x00\x00\x00\xF0\x9F\x99\x85\xF0\x9F\x99\x86") } end |