Skip to content

Commit 7faa076

Browse files
committed
Consider IPv4-mapped IPv6 addresses private if IPv4 address is private
Fixes [Bug #19479]
1 parent f9dc8ab commit 7faa076

File tree

2 files changed

+28
-2
lines changed

2 files changed

+28
-2
lines changed

lib/ipaddr.rb

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -263,15 +263,21 @@ def loopback?
263263
# Returns true if the ipaddr is a private address. IPv4 addresses
264264
# in 10.0.0.0/8, 172.16.0.0/12 and 192.168.0.0/16 as defined in RFC
265265
# 1918 and IPv6 Unique Local Addresses in fc00::/7 as defined in RFC
266-
# 4193 are considered private.
266+
# 4193 are considered private. Private IPv4 addresses in the
267+
# IPv4-mapped IPv6 address range are also considered private.
267268
def private?
268269
case @family
269270
when Socket::AF_INET
270271
@addr & 0xff000000 == 0x0a000000 || # 10.0.0.0/8
271272
@addr & 0xfff00000 == 0xac100000 || # 172.16.0.0/12
272273
@addr & 0xffff0000 == 0xc0a80000 # 192.168.0.0/16
273274
when Socket::AF_INET6
274-
@addr & 0xfe00_0000_0000_0000_0000_0000_0000_0000 == 0xfc00_0000_0000_0000_0000_0000_0000_0000
275+
@addr & 0xfe00_0000_0000_0000_0000_0000_0000_0000 == 0xfc00_0000_0000_0000_0000_0000_0000_0000 ||
276+
(@addr & 0xffff_0000_0000 == 0xffff_0000_0000 && (
277+
@addr & 0xff000000 == 0x0a000000 || # ::ffff:10.0.0.0/8
278+
@addr & 0xfff00000 == 0xac100000 || # ::ffff::172.16.0.0/12
279+
@addr & 0xffff0000 == 0xc0a80000 # ::ffff::192.168.0.0/16
280+
))
275281
else
276282
raise AddressFamilyError, "unsupported address family"
277283
end

test/test_ipaddr.rb

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -426,6 +426,26 @@ def test_private?
426426
assert_equal(true, IPAddr.new('fc84:8bf7:e905::1').private?)
427427
assert_equal(true, IPAddr.new('fd84:8bf7:e905::1').private?)
428428
assert_equal(false, IPAddr.new('fe84:8bf7:e905::1').private?)
429+
430+
assert_equal(false, IPAddr.new('::ffff:0.0.0.0').private?)
431+
assert_equal(false, IPAddr.new('::ffff:127.0.0.1').private?)
432+
433+
assert_equal(false, IPAddr.new('::ffff:8.8.8.8').private?)
434+
assert_equal(true, IPAddr.new('::ffff:10.0.0.0').private?)
435+
assert_equal(true, IPAddr.new('::ffff:10.255.255.255').private?)
436+
assert_equal(false, IPAddr.new('::ffff:11.255.1.1').private?)
437+
438+
assert_equal(false, IPAddr.new('::ffff:172.15.255.255').private?)
439+
assert_equal(true, IPAddr.new('::ffff:172.16.0.0').private?)
440+
assert_equal(true, IPAddr.new('::ffff:172.31.255.255').private?)
441+
assert_equal(false, IPAddr.new('::ffff:172.32.0.0').private?)
442+
443+
assert_equal(false, IPAddr.new('::ffff:190.168.0.0').private?)
444+
assert_equal(true, IPAddr.new('::ffff:192.168.0.0').private?)
445+
assert_equal(true, IPAddr.new('::ffff:192.168.255.255').private?)
446+
assert_equal(false, IPAddr.new('::ffff:192.169.0.0').private?)
447+
448+
assert_equal(false, IPAddr.new('::ffff:169.254.0.1').private?)
429449
end
430450

431451
def test_link_local?

0 commit comments

Comments
 (0)