[2.7] bpo-32502: Discard 64-bit (and other invalid) hardware addresses (GH-9125)

(cherry picked from commit 6b273f7f40)

Co-authored-by: Bo Bayles <bbayles@gmail.com>
This commit is contained in:
Chih-Hsuan Yen 2018-09-12 04:54:57 +08:00 committed by Benjamin Peterson
parent 253279c616
commit d919c60e69
3 changed files with 45 additions and 4 deletions

View File

@ -287,6 +287,39 @@ class TestUUID(unittest.TestCase):
node2 = uuid.getnode() node2 = uuid.getnode()
self.assertEqual(node1, node2, '%012x != %012x' % (node1, node2)) 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
uuid_real__node = uuid._node
uuid_real__NODE_GETTERS_WIN32 = uuid._NODE_GETTERS_WIN32
uuid_real__NODE_GETTERS_UNIX = uuid._NODE_GETTERS_UNIX
uuid._node = None
uuid._NODE_GETTERS_WIN32 = [too_large_getter]
uuid._NODE_GETTERS_UNIX = [too_large_getter]
try:
node = uuid.getnode()
finally:
uuid._node = uuid_real__node
uuid._NODE_GETTERS_WIN32 = uuid_real__NODE_GETTERS_WIN32
uuid._NODE_GETTERS_UNIX = uuid_real__NODE_GETTERS_UNIX
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:
uuid.uuid1(node=node)
except ValueError as e:
self.fail('uuid1 was given an invalid node ID')
@unittest.skipUnless(importable('ctypes'), 'requires ctypes') @unittest.skipUnless(importable('ctypes'), 'requires ctypes')
def test_uuid1(self): def test_uuid1(self):
equal = self.assertEqual equal = self.assertEqual

View File

@ -522,6 +522,11 @@ def _random_getnode():
_node = None _node = None
_NODE_GETTERS_WIN32 = [_windll_getnode, _netbios_getnode, _ipconfig_getnode]
_NODE_GETTERS_UNIX = [_unixdll_getnode, _ifconfig_getnode, _arp_getnode,
_lanscan_getnode, _netstat_getnode]
def getnode(): def getnode():
"""Get the hardware address as a 48-bit positive integer. """Get the hardware address as a 48-bit positive integer.
@ -537,18 +542,19 @@ def getnode():
import sys import sys
if sys.platform == 'win32': if sys.platform == 'win32':
getters = [_windll_getnode, _netbios_getnode, _ipconfig_getnode] getters = _NODE_GETTERS_WIN32
else: else:
getters = [_unixdll_getnode, _ifconfig_getnode, _arp_getnode, getters = _NODE_GETTERS_UNIX
_lanscan_getnode, _netstat_getnode]
for getter in getters + [_random_getnode]: for getter in getters + [_random_getnode]:
try: try:
_node = getter() _node = getter()
except: except:
continue continue
if _node is not None: if (_node is not None) and (0 <= _node < (1 << 48)):
return _node return _node
assert False, '_random_getnode() returned invalid value: {}'.format(_node)
_last_timestamp = None _last_timestamp = None

View File

@ -0,0 +1,2 @@
uuid.uuid1 no longer raises an exception if a 64-bit hardware address is
encountered.