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. |