bpo-32502: Discard 64-bit (and other invalid) hardware addresses (#5254) · python/cpython@6b273f7 (original) (raw)

3 files changed

lines changed

Original file line number Diff line number Diff line change
@@ -311,6 +311,32 @@ def test_getnode(self):
311 311 node2 = self.uuid.getnode()
312 312 self.assertEqual(node1, node2, '%012x != %012x' % (node1, node2))
313 313
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 +
314 340 def test_uuid1(self):
315 341 equal = self.assertEqual
316 342
Original file line number Diff line number Diff line change
@@ -656,7 +656,12 @@ def _random_getnode():
656 656
657 657 _node = None
658 658
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):
660 665 """Get the hardware address as a 48-bit positive integer.
661 666
662 667 The first time this runs, it may launch a separate program, which could
@@ -669,19 +674,18 @@ def getnode():
669 674 return _node
670 675
671 676 if sys.platform == 'win32':
672 -getters = [_windll_getnode, _netbios_getnode, _ipconfig_getnode]
677 +getters = _NODE_GETTERS_WIN32
673 678 else:
674 -getters = [_unix_getnode, _ifconfig_getnode, _ip_getnode,
675 -_arp_getnode, _lanscan_getnode, _netstat_getnode]
679 +getters = _NODE_GETTERS_UNIX
676 680
677 681 for getter in getters + [_random_getnode]:
678 682 try:
679 683 _node = getter()
680 684 except:
681 685 continue
682 -if _node is not None:
686 +if (_node is not None) and (0 <= _node < (1 << 48)):
683 687 return _node
684 -assert False, '_random_getnode() returned None'
688 +assert False, '_random_getnode() returned invalid value: {}'.format(_node)
685 689
686 690
687 691 _last_timestamp = None
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
1 +uuid.uuid1 no longer raises an exception if a 64-bit hardware address is
2 +encountered.