Skip to content

Commit 6b273f7

Browse files
bbayleswarsaw
authored andcommitted
bpo-32502: Discard 64-bit (and other invalid) hardware addresses (#5254)
1 parent 0bad4d6 commit 6b273f7

File tree

3 files changed

+38
-6
lines changed

3 files changed

+38
-6
lines changed

‎Lib/test/test_uuid.py‎

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -311,6 +311,32 @@ def test_getnode(self):
311311
node2 = self.uuid.getnode()
312312
self.assertEqual(node1, node2, '%012x != %012x' % (node1, node2))
313313

314+
# bpo-32502: UUID1 requires a 48-bit identifier, but hardware identifiers
315+
# need not necessarily be 48 bits (e.g., EUI-64).
316+
def test_uuid1_eui64(self):
317+
# Confirm that uuid.getnode ignores hardware addresses larger than 48
318+
# bits. Mock out each platform's *_getnode helper functions to return
319+
# something just larger than 48 bits to test. This will cause
320+
# uuid.getnode to fall back on uuid._random_getnode, which will
321+
# generate a valid value.
322+
too_large_getter = lambda: 1 << 48
323+
with unittest.mock.patch.multiple(
324+
self.uuid,
325+
_node=None, # Ignore any cached node value.
326+
_NODE_GETTERS_WIN32=[too_large_getter],
327+
_NODE_GETTERS_UNIX=[too_large_getter],
328+
):
329+
node = self.uuid.getnode()
330+
self.assertTrue(0 < node < (1 << 48), '%012x' % node)
331+
332+
# Confirm that uuid1 can use the generated node, i.e., the that
333+
# uuid.getnode fell back on uuid._random_getnode() rather than using
334+
# the value from too_large_getter above.
335+
try:
336+
self.uuid.uuid1(node=node)
337+
except ValueError as e:
338+
self.fail('uuid1 was given an invalid node ID')
339+
314340
def test_uuid1(self):
315341
equal = self.assertEqual
316342

‎Lib/uuid.py‎

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -656,7 +656,12 @@ def _random_getnode():
656656

657657
_node = None
658658

659-
def getnode():
659+
_NODE_GETTERS_WIN32 = [_windll_getnode, _netbios_getnode, _ipconfig_getnode]
660+
661+
_NODE_GETTERS_UNIX = [_unix_getnode, _ifconfig_getnode, _ip_getnode,
662+
_arp_getnode, _lanscan_getnode, _netstat_getnode]
663+
664+
def getnode(*, getters=None):
660665
"""Get the hardware address as a 48-bit positive integer.
661666
662667
The first time this runs, it may launch a separate program, which could
@@ -669,19 +674,18 @@ def getnode():
669674
return _node
670675

671676
if sys.platform == 'win32':
672-
getters = [_windll_getnode, _netbios_getnode, _ipconfig_getnode]
677+
getters = _NODE_GETTERS_WIN32
673678
else:
674-
getters = [_unix_getnode, _ifconfig_getnode, _ip_getnode,
675-
_arp_getnode, _lanscan_getnode, _netstat_getnode]
679+
getters = _NODE_GETTERS_UNIX
676680

677681
for getter in getters + [_random_getnode]:
678682
try:
679683
_node = getter()
680684
except:
681685
continue
682-
if _node is not None:
686+
if (_node is not None) and (0 <= _node < (1 << 48)):
683687
return _node
684-
assert False, '_random_getnode() returned None'
688+
assert False, '_random_getnode() returned invalid value: {}'.format(_node)
685689

686690

687691
_last_timestamp = None
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
uuid.uuid1 no longer raises an exception if a 64-bit hardware address is
2+
encountered.

0 commit comments

Comments
 (0)