Skip to content

Commit d919c60

Browse files
yan12125bbayles
authored andcommitted
[2.7] bpo-32502: Discard 64-bit (and other invalid) hardware addresses (GH-9125)
(cherry picked from commit 6b273f7) Co-authored-by: Bo Bayles <[email protected]>
1 parent 253279c commit d919c60

File tree

3 files changed

+45
-4
lines changed

3 files changed

+45
-4
lines changed

‎Lib/test/test_uuid.py‎

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -287,6 +287,39 @@ def test_getnode(self):
287287
node2 = uuid.getnode()
288288
self.assertEqual(node1, node2, '%012x != %012x' % (node1, node2))
289289

290+
# bpo-32502: UUID1 requires a 48-bit identifier, but hardware identifiers
291+
# need not necessarily be 48 bits (e.g., EUI-64).
292+
def test_uuid1_eui64(self):
293+
# Confirm that uuid.getnode ignores hardware addresses larger than 48
294+
# bits. Mock out each platform's *_getnode helper functions to return
295+
# something just larger than 48 bits to test. This will cause
296+
# uuid.getnode to fall back on uuid._random_getnode, which will
297+
# generate a valid value.
298+
too_large_getter = lambda: 1 << 48
299+
300+
uuid_real__node = uuid._node
301+
uuid_real__NODE_GETTERS_WIN32 = uuid._NODE_GETTERS_WIN32
302+
uuid_real__NODE_GETTERS_UNIX = uuid._NODE_GETTERS_UNIX
303+
uuid._node = None
304+
uuid._NODE_GETTERS_WIN32 = [too_large_getter]
305+
uuid._NODE_GETTERS_UNIX = [too_large_getter]
306+
try:
307+
node = uuid.getnode()
308+
finally:
309+
uuid._node = uuid_real__node
310+
uuid._NODE_GETTERS_WIN32 = uuid_real__NODE_GETTERS_WIN32
311+
uuid._NODE_GETTERS_UNIX = uuid_real__NODE_GETTERS_UNIX
312+
313+
self.assertTrue(0 < node < (1 << 48), '%012x' % node)
314+
315+
# Confirm that uuid1 can use the generated node, i.e., the that
316+
# uuid.getnode fell back on uuid._random_getnode() rather than using
317+
# the value from too_large_getter above.
318+
try:
319+
uuid.uuid1(node=node)
320+
except ValueError as e:
321+
self.fail('uuid1 was given an invalid node ID')
322+
290323
@unittest.skipUnless(importable('ctypes'), 'requires ctypes')
291324
def test_uuid1(self):
292325
equal = self.assertEqual

‎Lib/uuid.py‎

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -522,6 +522,11 @@ def _random_getnode():
522522

523523
_node = None
524524

525+
_NODE_GETTERS_WIN32 = [_windll_getnode, _netbios_getnode, _ipconfig_getnode]
526+
527+
_NODE_GETTERS_UNIX = [_unixdll_getnode, _ifconfig_getnode, _arp_getnode,
528+
_lanscan_getnode, _netstat_getnode]
529+
525530
def getnode():
526531
"""Get the hardware address as a 48-bit positive integer.
527532
@@ -537,18 +542,19 @@ def getnode():
537542

538543
import sys
539544
if sys.platform == 'win32':
540-
getters = [_windll_getnode, _netbios_getnode, _ipconfig_getnode]
545+
getters = _NODE_GETTERS_WIN32
541546
else:
542-
getters = [_unixdll_getnode, _ifconfig_getnode, _arp_getnode,
543-
_lanscan_getnode, _netstat_getnode]
547+
getters = _NODE_GETTERS_UNIX
544548

545549
for getter in getters + [_random_getnode]:
546550
try:
547551
_node = getter()
548552
except:
549553
continue
550-
if _node is not None:
554+
if (_node is not None) and (0 <= _node < (1 << 48)):
551555
return _node
556+
assert False, '_random_getnode() returned invalid value: {}'.format(_node)
557+
552558

553559
_last_timestamp = None
554560

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)