Skip to content

Commit d69794f

Browse files
bbayleswarsaw
authored andcommitted
[3.6] bpo-32502: Discard 64-bit (and other invalid) hardware addresses (GH-5254) (#5290)
* [3.6] bpo-32502: Discard 64-bit (and other invalid) hardware addresses (GH-5254). (cherry picked from commit 6b273f7)
1 parent 8e230e1 commit d69794f

File tree

3 files changed

+37
-4
lines changed

3 files changed

+37
-4
lines changed

Lib/test/test_uuid.py

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

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

Lib/uuid.py

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -540,6 +540,11 @@ def _random_getnode():
540540

541541
_node = None
542542

543+
_NODE_GETTERS_WIN32 = [_windll_getnode, _netbios_getnode, _ipconfig_getnode]
544+
545+
_NODE_GETTERS_UNIX = [_unixdll_getnode, _ifconfig_getnode, _ip_getnode,
546+
_arp_getnode, _lanscan_getnode, _netstat_getnode]
547+
543548
def getnode():
544549
"""Get the hardware address as a 48-bit positive integer.
545550
@@ -555,18 +560,18 @@ def getnode():
555560

556561
import sys
557562
if sys.platform == 'win32':
558-
getters = [_windll_getnode, _netbios_getnode, _ipconfig_getnode]
563+
getters = _NODE_GETTERS_WIN32
559564
else:
560-
getters = [_unixdll_getnode, _ifconfig_getnode, _ip_getnode,
561-
_arp_getnode, _lanscan_getnode, _netstat_getnode]
565+
getters = _NODE_GETTERS_UNIX
562566

563567
for getter in getters + [_random_getnode]:
564568
try:
565569
_node = getter()
566570
except:
567571
continue
568-
if _node is not None:
572+
if (_node is not None) and (0 <= _node < (1 << 48)):
569573
return _node
574+
assert False, '_random_getnode() returned invalid value: {}'.format(_node)
570575

571576
_last_timestamp = None
572577

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)