mirror of https://github.com/python/cpython.git
bpo-39991: Enhance uuid parser for MAC address (GH-19045)
Reject valid IPv6 addresses which doesn't contain "::" but have a length of 17 characters.
This commit is contained in:
parent
5b1ef200d3
commit
ebf6bb9f5e
|
@ -679,6 +679,58 @@ class TestUUIDWithExtModule(BaseTestUUID, unittest.TestCase):
|
||||||
class BaseTestInternals:
|
class BaseTestInternals:
|
||||||
_uuid = py_uuid
|
_uuid = py_uuid
|
||||||
|
|
||||||
|
def check_parse_mac(self, aix):
|
||||||
|
if not aix:
|
||||||
|
patch = mock.patch.multiple(self.uuid,
|
||||||
|
_MAC_DELIM=b':',
|
||||||
|
_MAC_OMITS_LEADING_ZEROES=False)
|
||||||
|
else:
|
||||||
|
patch = mock.patch.multiple(self.uuid,
|
||||||
|
_MAC_DELIM=b'.',
|
||||||
|
_MAC_OMITS_LEADING_ZEROES=True)
|
||||||
|
|
||||||
|
with patch:
|
||||||
|
# Valid MAC addresses
|
||||||
|
if not aix:
|
||||||
|
tests = (
|
||||||
|
(b'52:54:00:9d:0e:67', 0x5254009d0e67),
|
||||||
|
(b'12:34:56:78:90:ab', 0x1234567890ab),
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
# AIX format
|
||||||
|
tests = (
|
||||||
|
(b'fe.ad.c.1.23.4', 0xfead0c012304),
|
||||||
|
)
|
||||||
|
for mac, expected in tests:
|
||||||
|
self.assertEqual(self.uuid._parse_mac(mac), expected)
|
||||||
|
|
||||||
|
# Invalid MAC addresses
|
||||||
|
for mac in (
|
||||||
|
b'',
|
||||||
|
# IPv6 addresses with same length than valid MAC address
|
||||||
|
# (17 characters)
|
||||||
|
b'fe80::5054:ff:fe9',
|
||||||
|
b'123:2:3:4:5:6:7:8',
|
||||||
|
# empty 5rd field
|
||||||
|
b'52:54:00:9d::67',
|
||||||
|
# only 5 fields instead of 6
|
||||||
|
b'52:54:00:9d:0e'
|
||||||
|
# invalid character 'x'
|
||||||
|
b'52:54:00:9d:0e:6x'
|
||||||
|
# dash separator
|
||||||
|
b'52-54-00-9d-0e-67',
|
||||||
|
):
|
||||||
|
if aix:
|
||||||
|
mac = mac.replace(b':', b'.')
|
||||||
|
with self.subTest(mac=mac):
|
||||||
|
self.assertIsNone(self.uuid._parse_mac(mac))
|
||||||
|
|
||||||
|
def test_parse_mac(self):
|
||||||
|
self.check_parse_mac(False)
|
||||||
|
|
||||||
|
def test_parse_mac_aix(self):
|
||||||
|
self.check_parse_mac(True)
|
||||||
|
|
||||||
def test_find_under_heading(self):
|
def test_find_under_heading(self):
|
||||||
data = '''\
|
data = '''\
|
||||||
Name Mtu Network Address Ipkts Ierrs Opkts Oerrs Coll
|
Name Mtu Network Address Ipkts Ierrs Opkts Oerrs Coll
|
||||||
|
|
72
Lib/uuid.py
72
Lib/uuid.py
|
@ -434,6 +434,34 @@ def _find_mac_near_keyword(command, args, keywords, get_word_index):
|
||||||
return first_local_mac or None
|
return first_local_mac or None
|
||||||
|
|
||||||
|
|
||||||
|
def _parse_mac(word):
|
||||||
|
# Accept 'HH:HH:HH:HH:HH:HH' MAC address (ex: '52:54:00:9d:0e:67'),
|
||||||
|
# but reject IPv6 address (ex: 'fe80::5054:ff:fe9' or '123:2:3:4:5:6:7:8').
|
||||||
|
#
|
||||||
|
# Virtual interfaces, such as those provided by VPNs, do not have a
|
||||||
|
# colon-delimited MAC address as expected, but a 16-byte HWAddr separated
|
||||||
|
# by dashes. These should be ignored in favor of a real MAC address
|
||||||
|
parts = word.split(_MAC_DELIM)
|
||||||
|
if len(parts) != 6:
|
||||||
|
return
|
||||||
|
if _MAC_OMITS_LEADING_ZEROES:
|
||||||
|
# (Only) on AIX the macaddr value given is not prefixed by 0, e.g.
|
||||||
|
# en0 1500 link#2 fa.bc.de.f7.62.4 110854824 0 160133733 0 0
|
||||||
|
# not
|
||||||
|
# en0 1500 link#2 fa.bc.de.f7.62.04 110854824 0 160133733 0 0
|
||||||
|
if not all(1 <= len(part) <= 2 for part in parts):
|
||||||
|
return
|
||||||
|
hexstr = b''.join(part.rjust(2, b'0') for part in parts)
|
||||||
|
else:
|
||||||
|
if not all(len(part) == 2 for part in parts):
|
||||||
|
return
|
||||||
|
hexstr = b''.join(parts)
|
||||||
|
try:
|
||||||
|
return int(hexstr, 16)
|
||||||
|
except ValueError:
|
||||||
|
return
|
||||||
|
|
||||||
|
|
||||||
def _find_mac_under_heading(command, args, heading):
|
def _find_mac_under_heading(command, args, heading):
|
||||||
"""Looks for a MAC address under a heading in a command's output.
|
"""Looks for a MAC address under a heading in a command's output.
|
||||||
|
|
||||||
|
@ -453,39 +481,21 @@ def _find_mac_under_heading(command, args, heading):
|
||||||
|
|
||||||
first_local_mac = None
|
first_local_mac = None
|
||||||
for line in stdout:
|
for line in stdout:
|
||||||
|
words = line.rstrip().split()
|
||||||
try:
|
try:
|
||||||
words = line.rstrip().split()
|
|
||||||
word = words[column_index]
|
word = words[column_index]
|
||||||
# Accept 'HH:HH:HH:HH:HH:HH' MAC address (ex: '52:54:00:9d:0e:67'),
|
except IndexError:
|
||||||
# but reject IPv6 address (ex: 'fe80::5054:ff:fe9') detected
|
continue
|
||||||
# by '::' pattern.
|
|
||||||
if len(word) == 17 and b'::' not in word:
|
mac = _parse_mac(word)
|
||||||
mac = int(word.replace(_MAC_DELIM, b''), 16)
|
if mac is None:
|
||||||
elif _MAC_OMITS_LEADING_ZEROES:
|
continue
|
||||||
# (Only) on AIX the macaddr value given is not prefixed by 0, e.g.
|
if _is_universal(mac):
|
||||||
# en0 1500 link#2 fa.bc.de.f7.62.4 110854824 0 160133733 0 0
|
return mac
|
||||||
# not
|
if first_local_mac is None:
|
||||||
# en0 1500 link#2 fa.bc.de.f7.62.04 110854824 0 160133733 0 0
|
first_local_mac = mac
|
||||||
parts = word.split(_MAC_DELIM)
|
|
||||||
if len(parts) == 6 and all(0 < len(p) <= 2 for p in parts):
|
return first_local_mac
|
||||||
hexstr = b''.join(p.rjust(2, b'0') for p in parts)
|
|
||||||
mac = int(hexstr, 16)
|
|
||||||
else:
|
|
||||||
continue
|
|
||||||
else:
|
|
||||||
continue
|
|
||||||
except (ValueError, IndexError):
|
|
||||||
# Virtual interfaces, such as those provided by
|
|
||||||
# VPNs, do not have a colon-delimited MAC address
|
|
||||||
# as expected, but a 16-byte HWAddr separated by
|
|
||||||
# dashes. These should be ignored in favor of a
|
|
||||||
# real MAC address
|
|
||||||
pass
|
|
||||||
else:
|
|
||||||
if _is_universal(mac):
|
|
||||||
return mac
|
|
||||||
first_local_mac = first_local_mac or mac
|
|
||||||
return first_local_mac or None
|
|
||||||
|
|
||||||
|
|
||||||
# The following functions call external programs to 'get' a macaddr value to
|
# The following functions call external programs to 'get' a macaddr value to
|
||||||
|
|
Loading…
Reference in New Issue