]> granicus.if.org Git - python/commitdiff
bpo-26544: Fixed implementation of platform.libc_ver(). (GH-7684). (GH-8193) (GH...
authorMiss Islington (bot) <31488909+miss-islington@users.noreply.github.com>
Mon, 9 Jul 2018 11:38:27 +0000 (04:38 -0700)
committerSerhiy Storchaka <storchaka@gmail.com>
Mon, 9 Jul 2018 11:38:27 +0000 (14:38 +0300)
(cherry picked from commit 2a9b8babf0d09946ebebfdb2931cc0d3db5a1d3d)
(cherry picked from commit 7c43b801503c802ed6ea4b811f5bc73791249d94)

Doc/library/platform.rst
Lib/platform.py
Lib/test/test_platform.py
Misc/NEWS.d/next/Library/2018-06-13-20-33-29.bpo-26544.hQ1oMt.rst [new file with mode: 0644]

index f5cb52cb4745b4cf2d8049cf20b0e53a2906c50e..7d29dc186b67c7712319f38b15ad101ef05cb3ac 100644 (file)
@@ -270,7 +270,7 @@ Unix Platforms
    .. deprecated-removed:: 3.5 3.8
       See alternative like the `distro <https://pypi.org/project/distro>`_ package.
 
-.. function:: libc_ver(executable=sys.executable, lib='', version='', chunksize=2048)
+.. function:: libc_ver(executable=sys.executable, lib='', version='', chunksize=16384)
 
    Tries to determine the libc version against which the file executable (defaults
    to the Python interpreter) is linked.  Returns a tuple of strings ``(lib,
index cc2db9870d84b693d140d63c4d769fc48cbda3c5..c8e0476bfb21dbf7d44729d7b734a08668c2570a 100755 (executable)
@@ -144,9 +144,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.
@@ -161,6 +159,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
@@ -169,17 +168,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()]
@@ -189,12 +190,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
@@ -389,6 +390,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
index ea6752b61d8f77f165c16e76c96c88cc3971f6a1..afc4de3269079df132a45d263f9aee979a4d33fd 100644 (file)
@@ -270,7 +270,6 @@ class PlatformTest(unittest.TestCase):
             res = platform.dist()
 
     def test_libc_ver(self):
-        import os
         if os.path.isdir(sys.executable) and \
            os.path.exists(sys.executable+'.exe'):
             # Cygwin horror
@@ -279,6 +278,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_parse_release_file(self):
 
         for input, output in (
diff --git a/Misc/NEWS.d/next/Library/2018-06-13-20-33-29.bpo-26544.hQ1oMt.rst b/Misc/NEWS.d/next/Library/2018-06-13-20-33-29.bpo-26544.hQ1oMt.rst
new file mode 100644 (file)
index 0000000..e2cd0ba
--- /dev/null
@@ -0,0 +1,2 @@
+Fixed implementation of :func:`platform.libc_ver`. It almost always returned
+version '2.9' for glibc.