1
1
Fork 0
mirror of https://github.com/pypa/pip synced 2023-12-13 21:30:23 +01:00

Make have_compatible_glibc more robust against unusual version strings

Downstream forks/redistributors of glibc apparently sometimes add junk
onto the end of the version number -- e.g. Linaro glibc might have a
version number like "2.20-2014.11". This makes the glibc version number
parsing code ignore the rest of the string after the minor version
number, to be robust against Linaro's current usage, as well as whatever
exciting new weirdnesses that other redistributors might come up with
in the future.

Fixes: gh-3588
This commit is contained in:
Nathaniel J. Smith 2016-03-24 18:43:38 -07:00
parent 240385a35f
commit e01425d6e9
2 changed files with 37 additions and 7 deletions

View file

@ -163,6 +163,23 @@ def is_manylinux1_compatible():
return have_compatible_glibc(2, 5)
# Separated out from have_compatible_glibc for easier unit testing
def check_glibc_version(version_str, needed_major, needed_minor):
# Parse string and check against requested version.
#
# We use a regexp instead of str.split because we want to discard any
# random junk that might come after the minor version -- this might happen
# in patched/forked versions of glibc (e.g. Linaro's version of glibc
# uses version strings like "2.20-2014.11"). See gh-3588.
m = re.match(r"(?P<major>[0-9]+)\.(?P<minor>[0-9]+)", version_str)
if not m:
warnings.warn("Expected glibc version with 2 components major.minor,"
" got: %s" % version_str, RuntimeWarning)
return False
return (int(m.group("major")) == needed_major and
int(m.group("minor")) >= needed_minor)
def have_compatible_glibc(major, minimum_minor):
# ctypes.CDLL(None) internally calls dlopen(NULL), and as the dlopen
# manpage says, "If filename is NULL, then the returned handle is for the
@ -183,13 +200,7 @@ def have_compatible_glibc(major, minimum_minor):
if not isinstance(version_str, str):
version_str = version_str.decode("ascii")
# Parse string and check against requested version.
version = [int(piece) for piece in version_str.split(".")]
if len(version) < 2:
warnings.warn("Expected glibc version with 2 components major.minor,"
" got: %s" % version_str, RuntimeWarning)
return False
return version[0] == major and version[1] >= minimum_minor
return check_glibc_version(version_str, major, minimum_minor)
def get_darwin_arches(major, minor, machine):

View file

@ -159,3 +159,22 @@ class TestManylinux1Tags(object):
assert arches == ['manylinux1_x86_64', 'linux_x86_64', 'any']
else:
assert arches == ['manylinux1_x86_64', 'linux_x86_64']
def test_manylinux1_check_glibc_version(self):
"""
Test that the check_glibc_version function is robust against weird
glibc version strings.
"""
for two_twenty in ["2.20",
# used by "linaro glibc", see gh-3588
"2.20-2014.11",
# weird possibilities that I just made up
"2.20+dev",
"2.20-custom",
"2.20.1",
]:
assert pep425tags.check_glibc_version(two_twenty, 2, 15)
assert pep425tags.check_glibc_version(two_twenty, 2, 20)
assert not pep425tags.check_glibc_version(two_twenty, 2, 21)
assert not pep425tags.check_glibc_version(two_twenty, 3, 15)
assert not pep425tags.check_glibc_version(two_twenty, 1, 15)