at 23.05-pre 4.5 kB view raw
1From 9b5a023a5dc3127da15253f7acad71019395ebe1 Mon Sep 17 00:00:00 2001 2From: Pablo Galindo <Pablogsal@gmail.com> 3Date: Thu, 8 Oct 2020 19:50:37 +0100 4Subject: [PATCH] [3.7] bpo-41976: Fix the fallback to gcc of 5 ctypes.util.find_library when using gcc>9 (GH-22598). (GH-22601) 6 7(cherry picked from commit 27ac19cca2c639caaf6fedf3632fe6beb265f24f) 8 9Co-authored-by: Pablo Galindo <Pablogsal@gmail.com> 10--- 11 Lib/ctypes/test/test_find.py | 12 ++++++- 12 Lib/ctypes/util.py | 32 +++++++++++++++---- 13 .../2020-10-08-18-22-28.bpo-41976.Svm0wb.rst | 3 ++ 14 3 files changed, 39 insertions(+), 8 deletions(-) 15 create mode 100644 Misc/NEWS.d/next/Library/2020-10-08-18-22-28.bpo-41976.Svm0wb.rst 16 17diff --git a/Lib/ctypes/test/test_find.py b/Lib/ctypes/test/test_find.py 18index b99fdcba7b28f..92ac1840ad7d4 100644 19--- a/Lib/ctypes/test/test_find.py 20+++ b/Lib/ctypes/test/test_find.py 21@@ -1,4 +1,5 @@ 22 import unittest 23+import unittest.mock 24 import os.path 25 import sys 26 import test.support 27@@ -72,7 +73,7 @@ def test_shell_injection(self): 28 29 @unittest.skipUnless(sys.platform.startswith('linux'), 30 'Test only valid for Linux') 31-class LibPathFindTest(unittest.TestCase): 32+class FindLibraryLinux(unittest.TestCase): 33 def test_find_on_libpath(self): 34 import subprocess 35 import tempfile 36@@ -111,6 +112,15 @@ def test_find_on_libpath(self): 37 # LD_LIBRARY_PATH) 38 self.assertEqual(find_library(libname), 'lib%s.so' % libname) 39 40+ def test_find_library_with_gcc(self): 41+ with unittest.mock.patch("ctypes.util._findSoname_ldconfig", lambda *args: None): 42+ self.assertNotEqual(find_library('c'), None) 43+ 44+ def test_find_library_with_ld(self): 45+ with unittest.mock.patch("ctypes.util._findSoname_ldconfig", lambda *args: None), \ 46+ unittest.mock.patch("ctypes.util._findLib_gcc", lambda *args: None): 47+ self.assertNotEqual(find_library('c'), None) 48+ 49 50 if __name__ == "__main__": 51 unittest.main() 52diff --git a/Lib/ctypes/util.py b/Lib/ctypes/util.py 53index 97973bce001d9..0c2510e1619c8 100644 54--- a/Lib/ctypes/util.py 55+++ b/Lib/ctypes/util.py 56@@ -93,6 +93,12 @@ def find_library(name): 57 # Andreas Degert's find functions, using gcc, /sbin/ldconfig, objdump 58 import re, tempfile 59 60+ def _is_elf(filename): 61+ "Return True if the given file is an ELF file" 62+ elf_header = b'\x7fELF' 63+ with open(filename, 'br') as thefile: 64+ return thefile.read(4) == elf_header 65+ 66 def _findLib_gcc(name): 67 # Run GCC's linker with the -t (aka --trace) option and examine the 68 # library name it prints out. The GCC command will fail because we 69@@ -299,17 +312,22 @@ def _findLib_ld(name): 70 stderr=subprocess.PIPE, 71 universal_newlines=True) 72 out, _ = p.communicate() 73- res = re.search(expr, os.fsdecode(out)) 74- if res: 75- result = res.group(0) 76- except Exception as e: 77+ res = re.findall(expr, os.fsdecode(out)) 78+ for file in res: 79+ # Check if the given file is an elf file: gcc can report 80+ # some files that are linker scripts and not actual 81+ # shared objects. See bpo-41976 for more details 82+ if not _is_elf(file): 83+ continue 84+ return os.fsdecode(file) 85+ except Exception: 86 pass # result will be None 87 return result 88 89 def find_library(name): 90 # See issue #9998 91 return _findSoname_ldconfig(name) or \ 92- _get_soname(_findLib_gcc(name) or _findLib_ld(name)) 93+ _get_soname(_findLib_gcc(name)) or _get_soname(_findLib_ld(name)) 94 95 ################################################################ 96 # test code 97diff --git a/Misc/NEWS.d/next/Library/2020-10-08-18-22-28.bpo-41976.Svm0wb.rst b/Misc/NEWS.d/next/Library/2020-10-08-18-22-28.bpo-41976.Svm0wb.rst 98new file mode 100644 99index 0000000000000..c8b3fc771845e 100--- /dev/null 101+++ b/Misc/NEWS.d/next/Library/2020-10-08-18-22-28.bpo-41976.Svm0wb.rst 102@@ -0,0 +1,3 @@ 103+Fixed a bug that was causing :func:`ctypes.util.find_library` to return 104+``None`` when triying to locate a library in an environment when gcc>=9 is 105+available and ``ldconfig`` is not. Patch by Pablo Galindo