summaryrefslogtreecommitdiffstats
path: root/Lib
diff options
context:
space:
mode:
authorSerhiy Storchaka <storchaka@gmail.com>2018-07-09 08:47:45 (GMT)
committerGitHub <noreply@github.com>2018-07-09 08:47:45 (GMT)
commit2a9b8babf0d09946ebebfdb2931cc0d3db5a1d3d (patch)
tree6efcfbee7390ccdf8d969068b603b707fa769b27 /Lib
parentf85af035c5cb9a981f5e3164425f27cf73231b5f (diff)
downloadcpython-2a9b8babf0d09946ebebfdb2931cc0d3db5a1d3d.zip
cpython-2a9b8babf0d09946ebebfdb2931cc0d3db5a1d3d.tar.gz
cpython-2a9b8babf0d09946ebebfdb2931cc0d3db5a1d3d.tar.bz2
bpo-26544: Fixed implementation of platform.libc_ver(). (GH-7684)
Diffstat (limited to 'Lib')
-rwxr-xr-xLib/platform.py24
-rw-r--r--Lib/test/test_platform.py8
2 files changed, 20 insertions, 12 deletions
diff --git a/Lib/platform.py b/Lib/platform.py
index 6051f2b..a7785a2 100755
--- a/Lib/platform.py
+++ b/Lib/platform.py
@@ -140,9 +140,7 @@ _libc_search = re.compile(b'(__libc_init)'
b'|'
br'(libc(_\w+)?\.so(?:\.(\d[0-9.]*))?)', re.ASCII)
-def libc_ver(executable=sys.executable, lib='', version='',
-
- chunksize=16384):
+def libc_ver(executable=sys.executable, lib='', version='', chunksize=16384):
""" Tries to determine the libc version that the file executable
(which defaults to the Python interpreter) is linked against.
@@ -157,6 +155,7 @@ def libc_ver(executable=sys.executable, lib='', version='',
The file is read and scanned in chunks of chunksize bytes.
"""
+ from distutils.version import LooseVersion as V
if hasattr(os.path, 'realpath'):
# Python 2.2 introduced os.path.realpath(); it is used
# here to work around problems with Cygwin not being
@@ -165,17 +164,19 @@ def libc_ver(executable=sys.executable, lib='', version='',
with open(executable, 'rb') as f:
binary = f.read(chunksize)
pos = 0
- while 1:
+ while pos < len(binary):
if b'libc' in binary or b'GLIBC' in binary:
m = _libc_search.search(binary, pos)
else:
m = None
- if not m:
- binary = f.read(chunksize)
- if not binary:
+ if not m or m.end() == len(binary):
+ chunk = f.read(chunksize)
+ if chunk:
+ binary = binary[max(pos, len(binary) - 1000):] + chunk
+ pos = 0
+ continue
+ if not m:
break
- pos = 0
- continue
libcinit, glibc, glibcversion, so, threads, soversion = [
s.decode('latin1') if s is not None else s
for s in m.groups()]
@@ -185,12 +186,12 @@ def libc_ver(executable=sys.executable, lib='', version='',
if lib != 'glibc':
lib = 'glibc'
version = glibcversion
- elif glibcversion > version:
+ elif V(glibcversion) > V(version):
version = glibcversion
elif so:
if lib != 'glibc':
lib = 'libc'
- if soversion and soversion > version:
+ if soversion and (not version or V(soversion) > V(version)):
version = soversion
if threads and version[-len(threads):] != threads:
version = version + threads
@@ -253,6 +254,7 @@ def popen(cmd, mode='r', bufsize=-1):
warnings.warn('use os.popen instead', DeprecationWarning, stacklevel=2)
return os.popen(cmd, mode, bufsize)
+
def _norm_version(version, build=''):
""" Normalize the version and build strings and return a single
diff --git a/Lib/test/test_platform.py b/Lib/test/test_platform.py
index 7e3e401..9ecd5d9 100644
--- a/Lib/test/test_platform.py
+++ b/Lib/test/test_platform.py
@@ -260,7 +260,6 @@ class PlatformTest(unittest.TestCase):
self.assertEqual(sts, 0)
def test_libc_ver(self):
- import os
if os.path.isdir(sys.executable) and \
os.path.exists(sys.executable+'.exe'):
# Cygwin horror
@@ -269,6 +268,13 @@ class PlatformTest(unittest.TestCase):
executable = sys.executable
res = platform.libc_ver(executable)
+ self.addCleanup(support.unlink, support.TESTFN)
+ with open(support.TESTFN, 'wb') as f:
+ f.write(b'x'*(16384-10))
+ f.write(b'GLIBC_1.23.4\0GLIBC_1.9\0GLIBC_1.21\0')
+ self.assertEqual(platform.libc_ver(support.TESTFN),
+ ('glibc', '1.23.4'))
+
def test_popen(self):
mswindows = (sys.platform == "win32")