Skip to content

Commit 2a9b8ba

Browse files
bpo-26544: Fixed implementation of platform.libc_ver(). (GH-7684)
1 parent f85af03 commit 2a9b8ba

File tree

4 files changed

+23
-13
lines changed

4 files changed

+23
-13
lines changed

Doc/library/platform.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -243,7 +243,7 @@ Mac OS Platform
243243
Unix Platforms
244244
--------------
245245

246-
.. function:: libc_ver(executable=sys.executable, lib='', version='', chunksize=2048)
246+
.. function:: libc_ver(executable=sys.executable, lib='', version='', chunksize=16384)
247247

248248
Tries to determine the libc version against which the file executable (defaults
249249
to the Python interpreter) is linked. Returns a tuple of strings ``(lib,

Lib/platform.py

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -140,9 +140,7 @@
140140
b'|'
141141
br'(libc(_\w+)?\.so(?:\.(\d[0-9.]*))?)', re.ASCII)
142142

143-
def libc_ver(executable=sys.executable, lib='', version='',
144-
145-
chunksize=16384):
143+
def libc_ver(executable=sys.executable, lib='', version='', chunksize=16384):
146144

147145
""" Tries to determine the libc version that the file executable
148146
(which defaults to the Python interpreter) is linked against.
@@ -157,6 +155,7 @@ def libc_ver(executable=sys.executable, lib='', version='',
157155
The file is read and scanned in chunks of chunksize bytes.
158156
159157
"""
158+
from distutils.version import LooseVersion as V
160159
if hasattr(os.path, 'realpath'):
161160
# Python 2.2 introduced os.path.realpath(); it is used
162161
# here to work around problems with Cygwin not being
@@ -165,17 +164,19 @@ def libc_ver(executable=sys.executable, lib='', version='',
165164
with open(executable, 'rb') as f:
166165
binary = f.read(chunksize)
167166
pos = 0
168-
while 1:
167+
while pos < len(binary):
169168
if b'libc' in binary or b'GLIBC' in binary:
170169
m = _libc_search.search(binary, pos)
171170
else:
172171
m = None
173-
if not m:
174-
binary = f.read(chunksize)
175-
if not binary:
172+
if not m or m.end() == len(binary):
173+
chunk = f.read(chunksize)
174+
if chunk:
175+
binary = binary[max(pos, len(binary) - 1000):] + chunk
176+
pos = 0
177+
continue
178+
if not m:
176179
break
177-
pos = 0
178-
continue
179180
libcinit, glibc, glibcversion, so, threads, soversion = [
180181
s.decode('latin1') if s is not None else s
181182
for s in m.groups()]
@@ -185,12 +186,12 @@ def libc_ver(executable=sys.executable, lib='', version='',
185186
if lib != 'glibc':
186187
lib = 'glibc'
187188
version = glibcversion
188-
elif glibcversion > version:
189+
elif V(glibcversion) > V(version):
189190
version = glibcversion
190191
elif so:
191192
if lib != 'glibc':
192193
lib = 'libc'
193-
if soversion and soversion > version:
194+
if soversion and (not version or V(soversion) > V(version)):
194195
version = soversion
195196
if threads and version[-len(threads):] != threads:
196197
version = version + threads
@@ -253,6 +254,7 @@ def popen(cmd, mode='r', bufsize=-1):
253254
warnings.warn('use os.popen instead', DeprecationWarning, stacklevel=2)
254255
return os.popen(cmd, mode, bufsize)
255256

257+
256258
def _norm_version(version, build=''):
257259

258260
""" Normalize the version and build strings and return a single

Lib/test/test_platform.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -260,7 +260,6 @@ def test_mac_ver_with_fork(self):
260260
self.assertEqual(sts, 0)
261261

262262
def test_libc_ver(self):
263-
import os
264263
if os.path.isdir(sys.executable) and \
265264
os.path.exists(sys.executable+'.exe'):
266265
# Cygwin horror
@@ -269,6 +268,13 @@ def test_libc_ver(self):
269268
executable = sys.executable
270269
res = platform.libc_ver(executable)
271270

271+
self.addCleanup(support.unlink, support.TESTFN)
272+
with open(support.TESTFN, 'wb') as f:
273+
f.write(b'x'*(16384-10))
274+
f.write(b'GLIBC_1.23.4\0GLIBC_1.9\0GLIBC_1.21\0')
275+
self.assertEqual(platform.libc_ver(support.TESTFN),
276+
('glibc', '1.23.4'))
277+
272278
def test_popen(self):
273279
mswindows = (sys.platform == "win32")
274280

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Fixed implementation of :func:`platform.libc_ver`. It almost always returned
2+
version '2.9' for glibc.

0 commit comments

Comments
 (0)