]> granicus.if.org Git - python/commitdiff
bpo-32502: Discard 64-bit (and other invalid) hardware addresses (#5254)
authorBo Bayles <bbayles@gmail.com>
Wed, 24 Jan 2018 01:11:44 +0000 (19:11 -0600)
committerBarry Warsaw <barry@python.org>
Wed, 24 Jan 2018 01:11:44 +0000 (20:11 -0500)
Lib/test/test_uuid.py
Lib/uuid.py
Misc/NEWS.d/next/Library/2018-01-20-17-15-34.bpo-32502.OXJfn7.rst [new file with mode: 0644]

index f21bd6dfa15235667f4b5192be76441abfe8be43..7af1d7aec797c5f950646ece1e8d98c434b320cd 100644 (file)
@@ -311,6 +311,32 @@ class BaseTestUUID:
         node2 = self.uuid.getnode()
         self.assertEqual(node1, node2, '%012x != %012x' % (node1, node2))
 
+    # bpo-32502: UUID1 requires a 48-bit identifier, but hardware identifiers
+    # need not necessarily be 48 bits (e.g., EUI-64).
+    def test_uuid1_eui64(self):
+        # Confirm that uuid.getnode ignores hardware addresses larger than 48
+        # bits. Mock out each platform's *_getnode helper functions to return
+        # something just larger than 48 bits to test. This will cause
+        # uuid.getnode to fall back on uuid._random_getnode, which will
+        # generate a valid value.
+        too_large_getter = lambda: 1 << 48
+        with unittest.mock.patch.multiple(
+            self.uuid,
+            _node=None,  # Ignore any cached node value.
+            _NODE_GETTERS_WIN32=[too_large_getter],
+            _NODE_GETTERS_UNIX=[too_large_getter],
+        ):
+            node = self.uuid.getnode()
+        self.assertTrue(0 < node < (1 << 48), '%012x' % node)
+
+        # Confirm that uuid1 can use the generated node, i.e., the that
+        # uuid.getnode fell back on uuid._random_getnode() rather than using
+        # the value from too_large_getter above.
+        try:
+            self.uuid.uuid1(node=node)
+        except ValueError as e:
+            self.fail('uuid1 was given an invalid node ID')
+
     def test_uuid1(self):
         equal = self.assertEqual
 
index b7433cb71926acdb3fc12fff72448a8ec4f7c0f5..ef7b3b59241f4b4069e215a993d6574defae9aea 100644 (file)
@@ -656,7 +656,12 @@ def _random_getnode():
 
 _node = None
 
-def getnode():
+_NODE_GETTERS_WIN32 = [_windll_getnode, _netbios_getnode, _ipconfig_getnode]
+
+_NODE_GETTERS_UNIX = [_unix_getnode, _ifconfig_getnode, _ip_getnode,
+                      _arp_getnode, _lanscan_getnode, _netstat_getnode]
+
+def getnode(*, getters=None):
     """Get the hardware address as a 48-bit positive integer.
 
     The first time this runs, it may launch a separate program, which could
@@ -669,19 +674,18 @@ def getnode():
         return _node
 
     if sys.platform == 'win32':
-        getters = [_windll_getnode, _netbios_getnode, _ipconfig_getnode]
+        getters = _NODE_GETTERS_WIN32
     else:
-        getters = [_unix_getnode, _ifconfig_getnode, _ip_getnode,
-                   _arp_getnode, _lanscan_getnode, _netstat_getnode]
+        getters = _NODE_GETTERS_UNIX
 
     for getter in getters + [_random_getnode]:
         try:
             _node = getter()
         except:
             continue
-        if _node is not None:
+        if (_node is not None) and (0 <= _node < (1 << 48)):
             return _node
-    assert False, '_random_getnode() returned None'
+    assert False, '_random_getnode() returned invalid value: {}'.format(_node)
 
 
 _last_timestamp = None
diff --git a/Misc/NEWS.d/next/Library/2018-01-20-17-15-34.bpo-32502.OXJfn7.rst b/Misc/NEWS.d/next/Library/2018-01-20-17-15-34.bpo-32502.OXJfn7.rst
new file mode 100644 (file)
index 0000000..8338632
--- /dev/null
@@ -0,0 +1,2 @@
+uuid.uuid1 no longer raises an exception if a 64-bit hardware address is
+encountered.