Skip to content

Commit eb886db

Browse files
authored
bpo-39991: uuid._netstat_getnode() ignores IPv6 addresses (GH-19043)
uuid.getnode() now skips IPv6 addresses with the same string length than a MAC address (17 characters): only use MAC addresses.
1 parent a45b695 commit eb886db

File tree

3 files changed

+51
-10
lines changed

3 files changed

+51
-10
lines changed

Lib/test/test_uuid.py

Lines changed: 45 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,12 @@ def importable(name):
2323
return False
2424

2525

26+
def mock_get_command_stdout(data):
27+
def get_command_stdout(command, args):
28+
return io.BytesIO(data.encode())
29+
return get_command_stdout
30+
31+
2632
class BaseTestUUID:
2733
uuid = None
2834

@@ -673,7 +679,6 @@ class TestUUIDWithExtModule(BaseTestUUID, unittest.TestCase):
673679
class BaseTestInternals:
674680
_uuid = py_uuid
675681

676-
677682
def test_find_under_heading(self):
678683
data = '''\
679684
Name Mtu Network Address Ipkts Ierrs Opkts Oerrs Coll
@@ -685,15 +690,12 @@ def test_find_under_heading(self):
685690
224.0.0.1
686691
'''
687692

688-
def mock_get_command_stdout(command, args):
689-
return io.BytesIO(data.encode())
690-
691693
# The above data is from AIX - with '.' as _MAC_DELIM and strings
692694
# shorter than 17 bytes (no leading 0). (_MAC_OMITS_LEADING_ZEROES=True)
693695
with mock.patch.multiple(self.uuid,
694696
_MAC_DELIM=b'.',
695697
_MAC_OMITS_LEADING_ZEROES=True,
696-
_get_command_stdout=mock_get_command_stdout):
698+
_get_command_stdout=mock_get_command_stdout(data)):
697699
mac = self.uuid._find_mac_under_heading(
698700
command='netstat',
699701
args='-ian',
@@ -702,6 +704,43 @@ def mock_get_command_stdout(command, args):
702704

703705
self.assertEqual(mac, 0xfead0c012304)
704706

707+
def test_find_under_heading_ipv6(self):
708+
# bpo-39991: IPv6 address "fe80::5054:ff:fe9" looks like a MAC address
709+
# (same string length) but must be skipped
710+
data = '''\
711+
Name Mtu Network Address Ipkts Ierrs Idrop Opkts Oerrs Coll
712+
vtnet 1500 <Link#1> 52:54:00:9d:0e:67 10017 0 0 8174 0 0
713+
vtnet - fe80::%vtnet0 fe80::5054:ff:fe9 0 - - 4 - -
714+
vtnet - 192.168.122.0 192.168.122.45 8844 - - 8171 - -
715+
lo0 16384 <Link#2> lo0 260148 0 0 260148 0 0
716+
lo0 - ::1/128 ::1 193 - - 193 - -
717+
ff01::1%lo0
718+
ff02::2:2eb7:74fa
719+
ff02::2:ff2e:b774
720+
ff02::1%lo0
721+
ff02::1:ff00:1%lo
722+
lo0 - fe80::%lo0/64 fe80::1%lo0 0 - - 0 - -
723+
ff01::1%lo0
724+
ff02::2:2eb7:74fa
725+
ff02::2:ff2e:b774
726+
ff02::1%lo0
727+
ff02::1:ff00:1%lo
728+
lo0 - 127.0.0.0/8 127.0.0.1 259955 - - 259955 - -
729+
224.0.0.1
730+
'''
731+
732+
with mock.patch.multiple(self.uuid,
733+
_MAC_DELIM=b':',
734+
_MAC_OMITS_LEADING_ZEROES=False,
735+
_get_command_stdout=mock_get_command_stdout(data)):
736+
mac = self.uuid._find_mac_under_heading(
737+
command='netstat',
738+
args='-ian',
739+
heading=b'Address',
740+
)
741+
742+
self.assertEqual(mac, 0x5254009d0e67)
743+
705744
def test_find_mac_near_keyword(self):
706745
# key and value are on the same line
707746
data = '''
@@ -710,14 +749,11 @@ def test_find_mac_near_keyword(self):
710749
eth0 Link encap:Ethernet HWaddr 12:34:56:78:90:ab
711750
'''
712751

713-
def mock_get_command_stdout(command, args):
714-
return io.BytesIO(data.encode())
715-
716752
# The above data will only be parsed properly on non-AIX unixes.
717753
with mock.patch.multiple(self.uuid,
718754
_MAC_DELIM=b':',
719755
_MAC_OMITS_LEADING_ZEROES=False,
720-
_get_command_stdout=mock_get_command_stdout):
756+
_get_command_stdout=mock_get_command_stdout(data)):
721757
mac = self.uuid._find_mac_near_keyword(
722758
command='ifconfig',
723759
args='',

Lib/uuid.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -456,7 +456,10 @@ def _find_mac_under_heading(command, args, heading):
456456
try:
457457
words = line.rstrip().split()
458458
word = words[column_index]
459-
if len(word) == 17:
459+
# Accept 'HH:HH:HH:HH:HH:HH' MAC address (ex: '52:54:00:9d:0e:67'),
460+
# but reject IPv6 address (ex: 'fe80::5054:ff:fe9') detected
461+
# by '::' pattern.
462+
if len(word) == 17 and b'::' not in word:
460463
mac = int(word.replace(_MAC_DELIM, b''), 16)
461464
elif _MAC_OMITS_LEADING_ZEROES:
462465
# (Only) on AIX the macaddr value given is not prefixed by 0, e.g.
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
:func:`uuid.getnode` now skips IPv6 addresses with the same string length
2+
than a MAC address (17 characters): only use MAC addresses.

0 commit comments

Comments
 (0)