[Python-checkins] bpo-39991: uuid._netstat_getnode() ignores IPv6 addresses (GH-19043)

Victor Stinner webhook-mailer at python.org
Tue Mar 17 10:51:50 EDT 2020


https://github.com/python/cpython/commit/eb886db1e99a15f15a2342aa496197a5f88fa9c8
commit: eb886db1e99a15f15a2342aa496197a5f88fa9c8
branch: master
author: Victor Stinner <vstinner at python.org>
committer: GitHub <noreply at github.com>
date: 2020-03-17T15:51:42+01:00
summary:

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.

files:
A Misc/NEWS.d/next/Library/2020-03-17-12-40-38.bpo-39991.hLPPs4.rst
M Lib/test/test_uuid.py
M Lib/uuid.py

diff --git a/Lib/test/test_uuid.py b/Lib/test/test_uuid.py
index b76c60e1ce28b..3b013a8ef5ebf 100644
--- a/Lib/test/test_uuid.py
+++ b/Lib/test/test_uuid.py
@@ -23,6 +23,12 @@ def importable(name):
         return False
 
 
+def mock_get_command_stdout(data):
+    def get_command_stdout(command, args):
+        return io.BytesIO(data.encode())
+    return get_command_stdout
+
+
 class BaseTestUUID:
     uuid = None
 
@@ -673,7 +679,6 @@ class TestUUIDWithExtModule(BaseTestUUID, unittest.TestCase):
 class BaseTestInternals:
     _uuid = py_uuid
 
-
     def test_find_under_heading(self):
         data = '''\
 Name  Mtu   Network     Address           Ipkts Ierrs    Opkts Oerrs  Coll
@@ -685,15 +690,12 @@ def test_find_under_heading(self):
                         224.0.0.1
 '''
 
-        def mock_get_command_stdout(command, args):
-            return io.BytesIO(data.encode())
-
         # The above data is from AIX - with '.' as _MAC_DELIM and strings
         # shorter than 17 bytes (no leading 0). (_MAC_OMITS_LEADING_ZEROES=True)
         with mock.patch.multiple(self.uuid,
                                  _MAC_DELIM=b'.',
                                  _MAC_OMITS_LEADING_ZEROES=True,
-                                 _get_command_stdout=mock_get_command_stdout):
+                                 _get_command_stdout=mock_get_command_stdout(data)):
             mac = self.uuid._find_mac_under_heading(
                 command='netstat',
                 args='-ian',
@@ -702,6 +704,43 @@ def mock_get_command_stdout(command, args):
 
         self.assertEqual(mac, 0xfead0c012304)
 
+    def test_find_under_heading_ipv6(self):
+        # bpo-39991: IPv6 address "fe80::5054:ff:fe9" looks like a MAC address
+        # (same string length) but must be skipped
+        data = '''\
+Name    Mtu Network       Address              Ipkts Ierrs Idrop    Opkts Oerrs  Coll
+vtnet  1500 <Link#1>      52:54:00:9d:0e:67    10017     0     0     8174     0     0
+vtnet     - fe80::%vtnet0 fe80::5054:ff:fe9        0     -     -        4     -     -
+vtnet     - 192.168.122.0 192.168.122.45        8844     -     -     8171     -     -
+lo0   16384 <Link#2>      lo0                 260148     0     0   260148     0     0
+lo0       - ::1/128       ::1                    193     -     -      193     -     -
+                          ff01::1%lo0
+                          ff02::2:2eb7:74fa
+                          ff02::2:ff2e:b774
+                          ff02::1%lo0
+                          ff02::1:ff00:1%lo
+lo0       - fe80::%lo0/64 fe80::1%lo0              0     -     -        0     -     -
+                          ff01::1%lo0
+                          ff02::2:2eb7:74fa
+                          ff02::2:ff2e:b774
+                          ff02::1%lo0
+                          ff02::1:ff00:1%lo
+lo0       - 127.0.0.0/8   127.0.0.1           259955     -     -   259955     -     -
+                          224.0.0.1
+'''
+
+        with mock.patch.multiple(self.uuid,
+                                 _MAC_DELIM=b':',
+                                 _MAC_OMITS_LEADING_ZEROES=False,
+                                 _get_command_stdout=mock_get_command_stdout(data)):
+            mac = self.uuid._find_mac_under_heading(
+                command='netstat',
+                args='-ian',
+                heading=b'Address',
+            )
+
+        self.assertEqual(mac, 0x5254009d0e67)
+
     def test_find_mac_near_keyword(self):
         # key and value are on the same line
         data = '''
@@ -710,14 +749,11 @@ def test_find_mac_near_keyword(self):
 eth0      Link encap:Ethernet  HWaddr 12:34:56:78:90:ab
 '''
 
-        def mock_get_command_stdout(command, args):
-            return io.BytesIO(data.encode())
-
         # The above data will only be parsed properly on non-AIX unixes.
         with mock.patch.multiple(self.uuid,
                                  _MAC_DELIM=b':',
                                  _MAC_OMITS_LEADING_ZEROES=False,
-                                 _get_command_stdout=mock_get_command_stdout):
+                                 _get_command_stdout=mock_get_command_stdout(data)):
             mac = self.uuid._find_mac_near_keyword(
                 command='ifconfig',
                 args='',
diff --git a/Lib/uuid.py b/Lib/uuid.py
index 224a766ff2297..3b3abc2a45543 100644
--- a/Lib/uuid.py
+++ b/Lib/uuid.py
@@ -456,7 +456,10 @@ def _find_mac_under_heading(command, args, heading):
         try:
             words = line.rstrip().split()
             word = words[column_index]
-            if len(word) == 17:
+            # Accept 'HH:HH:HH:HH:HH:HH' MAC address (ex: '52:54:00:9d:0e:67'),
+            # but reject IPv6 address (ex: 'fe80::5054:ff:fe9') detected
+            # by '::' pattern.
+            if len(word) == 17 and b'::' not in word:
                 mac = int(word.replace(_MAC_DELIM, b''), 16)
             elif _MAC_OMITS_LEADING_ZEROES:
                 # (Only) on AIX the macaddr value given is not prefixed by 0, e.g.
diff --git a/Misc/NEWS.d/next/Library/2020-03-17-12-40-38.bpo-39991.hLPPs4.rst b/Misc/NEWS.d/next/Library/2020-03-17-12-40-38.bpo-39991.hLPPs4.rst
new file mode 100644
index 0000000000000..ef5a9e4d67375
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2020-03-17-12-40-38.bpo-39991.hLPPs4.rst
@@ -0,0 +1,2 @@
+:func:`uuid.getnode` now skips IPv6 addresses with the same string length
+than a MAC address (17 characters): only use MAC addresses.



More information about the Python-checkins mailing list