]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
bpo-41043: Escape literal part of the path for glob(). (GH-20994)
authorSerhiy Storchaka <storchaka@gmail.com>
Sat, 20 Jun 2020 08:10:31 +0000 (11:10 +0300)
committerGitHub <noreply@github.com>
Sat, 20 Jun 2020 08:10:31 +0000 (11:10 +0300)
24 files changed:
Lib/distutils/command/build_py.py
Lib/idlelib/tree.py
Lib/imghdr.py
Lib/pdb.py
Lib/sndhdr.py
Lib/test/_test_multiprocessing.py
Lib/test/libregrtest/main.py
Lib/test/support/__init__.py
Lib/test/test_bz2.py
Lib/test/test_crashers.py
Lib/test/test_dbm.py
Lib/test/test_import/__init__.py
Lib/test/test_mailbox.py
Lib/test/test_regrtest.py
Lib/test/test_site.py
Lib/test/test_tokenize.py
Lib/test/test_unicode_file.py
Lib/webbrowser.py
Misc/NEWS.d/next/Library/2020-06-20-00-19-30.bpo-41043.p-Pk-H.rst [new file with mode: 0644]
Tools/c-analyzer/c_analyzer/common/files.py
Tools/c-analyzer/check-c-globals.py
Tools/peg_generator/scripts/test_parse_directory.py
Tools/ssl/make_ssl_data.py
setup.py

index cf0ca57c320472262b03e6abc487ea4224556cc6..edc2171cd122dda26a96a2770d2cfa69ccab417b 100644 (file)
@@ -5,7 +5,7 @@ Implements the Distutils 'build_py' command."""
 import os
 import importlib.util
 import sys
-from glob import glob
+import glob
 
 from distutils.core import Command
 from distutils.errors import *
@@ -125,7 +125,7 @@ class build_py (Command):
         files = []
         for pattern in globs:
             # Each pattern has to be converted to a platform-specific path
-            filelist = glob(os.path.join(src_dir, convert_path(pattern)))
+            filelist = glob.glob(os.path.join(glob.escape(src_dir), convert_path(pattern)))
             # Files that match more than one pattern are only added once
             files.extend([fn for fn in filelist if fn not in files
                 and os.path.isfile(fn)])
@@ -216,7 +216,7 @@ class build_py (Command):
 
     def find_package_modules(self, package, package_dir):
         self.check_package(package, package_dir)
-        module_files = glob(os.path.join(package_dir, "*.py"))
+        module_files = glob.glob(os.path.join(glob.escape(package_dir), "*.py"))
         modules = []
         setup_script = os.path.abspath(self.distribution.script_name)
 
index 6229be4e5a8ad5cae0ce2fa0a11d114eb1e1bb90..5947268f5c35aead90951dbd2eae9475d37e5531 100644 (file)
@@ -38,7 +38,7 @@ def listicons(icondir=ICONDIR):
     """Utility to display the available icons."""
     root = Tk()
     import glob
-    list = glob.glob(os.path.join(icondir, "*.gif"))
+    list = glob.glob(os.path.join(glob.escape(icondir), "*.gif"))
     list.sort()
     images = []
     row = column = 0
index 76e8abb2d5833d487ba94e9ebe31f66e1fb9df0c..6e01fd857469ad89e597009d8c1aa093f2f90313 100644 (file)
@@ -152,7 +152,7 @@ def testall(list, recursive, toplevel):
             if recursive or toplevel:
                 print('recursing down:')
                 import glob
-                names = glob.glob(os.path.join(filename, '*'))
+                names = glob.glob(os.path.join(glob.escape(filename), '*'))
                 testall(names, recursive, 0)
             else:
                 print('*** directory (use -r) ***')
index bf503f1e73ee1412908954dd5cdaf1f3e57168f7..701386e8b96c29094b33a18387025823440f7bff 100755 (executable)
@@ -473,7 +473,7 @@ class Pdb(bdb.Bdb, cmd.Cmd):
         except Exception:
             ret = []
         # Then, try to complete file names as well.
-        globs = glob.glob(text + '*')
+        globs = glob.glob(glob.escape(text) + '*')
         for fn in globs:
             if os.path.isdir(fn):
                 ret.append(fn + '/')
index 594353136f5c374effa7aa6db6f4f75e0e99eb7a..96595c6974468213e0a93414af95f4981bb609c5 100644 (file)
@@ -241,7 +241,7 @@ def testall(list, recursive, toplevel):
             if recursive or toplevel:
                 print('recursing down:')
                 import glob
-                names = glob.glob(os.path.join(filename, '*'))
+                names = glob.glob(os.path.join(glob.escape(filename), '*'))
                 testall(names, recursive, 0)
             else:
                 print('*** directory (use -r) ***')
index 444e234509c27342dcd11fc664c1e6fa5eb29ebb..5f65d966d62eea9f19b9e991dcd0d45eb4499e6a 100644 (file)
@@ -4260,7 +4260,7 @@ class _TestImportStar(unittest.TestCase):
     def get_module_names(self):
         import glob
         folder = os.path.dirname(multiprocessing.__file__)
-        pattern = os.path.join(folder, '*.py')
+        pattern = os.path.join(glob.escape(folder), '*.py')
         files = glob.glob(pattern)
         modules = [os.path.splitext(os.path.split(f)[1])[0] for f in files]
         modules = ['multiprocessing.' + m for m in modules]
index 95b4856c8bed7d7aefdf14ccea026ff56124d793..adf31cc94940d1c106ad18757f62d5cd7f510ece 100644 (file)
@@ -602,7 +602,7 @@ class Regrtest:
     def cleanup(self):
         import glob
 
-        path = os.path.join(self.tmp_dir, 'test_python_*')
+        path = os.path.join(glob.escape(self.tmp_dir), 'test_python_*')
         print("Cleanup %s directory" % self.tmp_dir)
         for name in glob.glob(path):
             if os.path.isdir(name):
index bceb8cda20c35e5b9a741f56e31c3700d18f4bf1..5707d8eeaa28b59fb6b2a52ad9879b7bcd4c1385 100644 (file)
@@ -1345,7 +1345,7 @@ class PythonSymlink:
                 dll,
                 os.path.join(dest_dir, os.path.basename(dll))
             ))
-            for runtime in glob.glob(os.path.join(src_dir, "vcruntime*.dll")):
+            for runtime in glob.glob(os.path.join(glob.escape(src_dir), "vcruntime*.dll")):
                 self._also_link.append((
                     runtime,
                     os.path.join(dest_dir, os.path.basename(runtime))
index 91ccff2d0c07f8da812d4c931bf4b286bba2390e..8f0773d55faeff5f577899fbfc2ae3e2f6bfe9da 100644 (file)
@@ -70,7 +70,7 @@ class BaseTest(unittest.TestCase):
     # simply use the bigger test data for all tests.
     test_size = 0
     BIG_TEXT = bytearray(128*1024)
-    for fname in glob.glob(os.path.join(os.path.dirname(__file__), '*.py')):
+    for fname in glob.glob(os.path.join(glob.escape(os.path.dirname(__file__)), '*.py')):
         with open(fname, 'rb') as fh:
             test_size += fh.readinto(memoryview(BIG_TEXT)[test_size:])
         if test_size > 128*1024:
index 58dfd001da3627fd96f49922dd63078bc7e9cc78..31b712028f8a127c7f9e065cfa59971913187848 100644 (file)
@@ -11,7 +11,7 @@ import test.support
 from test.support.script_helper import assert_python_failure
 
 CRASHER_DIR = os.path.join(os.path.dirname(__file__), "crashers")
-CRASHER_FILES = os.path.join(CRASHER_DIR, "*.py")
+CRASHER_FILES = os.path.join(glob.escape(CRASHER_DIR), "*.py")
 
 infinite_loops = ["infinite_loop_re.py", "nasty_eq_vs_dict.py"]
 
index 1db3bef6f41367648c58810161e3b320f40a4de9..571da973aab0ee10f5d04497d81164dc220559af 100644 (file)
@@ -33,7 +33,7 @@ def dbm_iterator():
 def delete_files():
     # we don't know the precise name the underlying database uses
     # so we use glob to locate all names
-    for f in glob.glob(_fname + "*"):
+    for f in glob.glob(glob.escape(_fname) + "*"):
         test.support.unlink(f)
 
 
index 060d145970ee95b4d04a37d4b567c1a98619210c..a04cf65945e935bdacc1cb7843f96406f9bc2de1 100644 (file)
@@ -486,7 +486,7 @@ class ImportTests(unittest.TestCase):
             pyexe = os.path.join(tmp, os.path.basename(sys.executable))
             shutil.copy(sys.executable, pyexe)
             shutil.copy(dllname, tmp)
-            for f in glob.glob(os.path.join(sys.prefix, "vcruntime*.dll")):
+            for f in glob.glob(os.path.join(glob.escape(sys.prefix), "vcruntime*.dll")):
                 shutil.copy(f, tmp)
 
             shutil.copy(pydname, tmp2)
index fdda1d11d3307efdeb14c2596f937915e98667c7..6f891d413cd8f1533ba719cf27d268e0d323b45c 100644 (file)
@@ -979,7 +979,7 @@ class _TestMboxMMDF(_TestSingleFile):
         super().tearDown()
         self._box.close()
         self._delete_recursively(self._path)
-        for lock_remnant in glob.glob(self._path + '.*'):
+        for lock_remnant in glob.glob(glob.escape(self._path) + '.*'):
             support.unlink(lock_remnant)
 
     def assertMailboxEmpty(self):
@@ -1311,7 +1311,7 @@ class TestBabyl(_TestSingleFile, unittest.TestCase):
         super().tearDown()
         self._box.close()
         self._delete_recursively(self._path)
-        for lock_remnant in glob.glob(self._path + '.*'):
+        for lock_remnant in glob.glob(glob.escape(self._path) + '.*'):
             support.unlink(lock_remnant)
 
     def test_labels(self):
index de209da41a34dcbc47bc2350acdc06e0401ffaef..6745be6fea1acf93720ffea1fea37dafb614a1cb 100644 (file)
@@ -556,7 +556,7 @@ class CheckActualTests(BaseTestCase):
         args = ['-Wd', '-E', '-bb', '-m', 'test.regrtest', '--list-tests']
         output = self.run_python(args)
         rough_number_of_tests_found = len(output.splitlines())
-        actual_testsuite_glob = os.path.join(os.path.dirname(__file__),
+        actual_testsuite_glob = os.path.join(glob.escape(os.path.dirname(__file__)),
                                              'test*.py')
         rough_counted_test_py_files = len(glob.glob(actual_testsuite_glob))
         # We're not trying to duplicate test finding logic in here,
index 9f4a8bc64f7eee14cb16030b806f2489c328ae13..9751c64c99e74a6531a1dd7f4fe3728a5ca92c8d 100644 (file)
@@ -543,7 +543,7 @@ class StartupImportTests(unittest.TestCase):
         # found in sys.path (see site.addpackage()). Skip the test if at least
         # one .pth file is found.
         for path in isolated_paths:
-            pth_files = glob.glob(os.path.join(path, "*.pth"))
+            pth_files = glob.glob(os.path.join(glob.escape(path), "*.pth"))
             if pth_files:
                 self.skipTest(f"found {len(pth_files)} .pth files in: {path}")
 
index 4c90092893a224d0486a2fc839964de99bcbbf05..6de7aa87bb2f9e39ee7a28f4c2cb65a2f4e39b03 100644 (file)
@@ -1605,7 +1605,7 @@ class TestRoundtrip(TestCase):
         import glob, random
         fn = support.findfile("tokenize_tests.txt")
         tempdir = os.path.dirname(fn) or os.curdir
-        testfiles = glob.glob(os.path.join(tempdir, "test*.py"))
+        testfiles = glob.glob(os.path.join(glob.escape(tempdir), "test*.py"))
 
         # Tokenize is broken on test_pep3131.py because regular expressions are
         # broken on the obscure unicode identifiers in it. *sigh*
index ed1f6cecc7856822fb8cbeaf77ea2036a78d33f5..46a0d062540b78a9c44cbe5f6d87978491c2b15c 100644 (file)
@@ -41,7 +41,7 @@ class TestUnicodeFiles(unittest.TestCase):
         self._do_copyish(filename, filename)
         # Filename should appear in glob output
         self.assertTrue(
-            os.path.abspath(filename)==os.path.abspath(glob.glob(filename)[0]))
+            os.path.abspath(filename)==os.path.abspath(glob.glob(glob.escape(filename))[0]))
         # basename should appear in listdir.
         path, base = os.path.split(os.path.abspath(filename))
         file_list = os.listdir(path)
index 3dcf66b65982507148fa0a2d681b144b3d092809..31e1df42479462f77702692db6f49bf0bf17c21a 100755 (executable)
@@ -413,7 +413,7 @@ class Grail(BaseBrowser):
         tempdir = os.path.join(tempfile.gettempdir(),
                                ".grail-unix")
         user = pwd.getpwuid(os.getuid())[0]
-        filename = os.path.join(tempdir, user + "-*")
+        filename = os.path.join(glob.escape(tempdir), glob.escape(user) + "-*")
         maybes = glob.glob(filename)
         if not maybes:
             return None
diff --git a/Misc/NEWS.d/next/Library/2020-06-20-00-19-30.bpo-41043.p-Pk-H.rst b/Misc/NEWS.d/next/Library/2020-06-20-00-19-30.bpo-41043.p-Pk-H.rst
new file mode 100644 (file)
index 0000000..9c6020e
--- /dev/null
@@ -0,0 +1,2 @@
+Fixed the use of :func:`~glob.glob` in the stdlib: literal part of the path
+is now always correctly escaped.
index ab551a84bad15dcb6c1e9fc1c290d3ff92154f7a..f630afe62592424f43d899768e578ecdb233ebb3 100644 (file)
@@ -41,6 +41,8 @@ def walk_tree(root, *,
 def glob_tree(root, *,
               suffix=None,
               _glob=glob.iglob,
+              _escape=glob.escape,
+              _join=os.path.join,
               ):
     """Yield each file in the tree under the given directory name.
 
@@ -51,9 +53,9 @@ def glob_tree(root, *,
     if not isinstance(suffix, str):
         raise ValueError('suffix must be a string')
 
-    for filename in _glob(f'{root}/*{suffix}'):
+    for filename in _glob(_join(_escape(root), f'*{suffix}')):
         yield filename
-    for filename in _glob(f'{root}/**/*{suffix}'):
+    for filename in _glob(_join(_escape(root), f'**/*{suffix}')):
         yield filename
 
 
index e68ed9271fe48df37551a0ec74181d141fdf16b5..1371f927423279d3eb042f8dfee7b5f16d0959fc 100644 (file)
@@ -37,7 +37,9 @@ IGNORED_VARS = {
 def find_capi_vars(root):
     capi_vars = {}
     for dirname in SOURCE_DIRS:
-        for filename in glob.glob(os.path.join(ROOT_DIR, dirname, '**/*.[hc]'),
+        for filename in glob.glob(os.path.join(
+                                  glob.escape(os.path.join(ROOT_DIR, dirname)),
+                                  '**/*.[hc]'),
                                   recursive=True):
             with open(filename) as file:
                 for name in _find_capi_vars(file):
index d8f4f0ecd3e05671b4dcf2e213a130d69316d45a..a5e26f0a0feda5d2a230e61881ed0f88b6e9db58 100755 (executable)
@@ -7,7 +7,7 @@ import sys
 import time
 import traceback
 import tokenize
-from glob import glob
+from glob import glob, escape
 from pathlib import PurePath
 
 from typing import List, Optional, Any, Tuple
@@ -109,7 +109,7 @@ def parse_directory(directory: str, verbose: bool, excluded_files: List[str], sh
     files = []
     total_seconds = 0
 
-    for file in sorted(glob(f"{directory}/**/*.py", recursive=True)):
+    for file in sorted(glob(os.path.join(escape(directory), f"**/*.py"), recursive=True)):
         # Only attempt to parse Python files and files that are not excluded
         if any(PurePath(file).match(pattern) for pattern in excluded_files):
             continue
index a29c04ab57183065adf4fc9229d6d4014fc1aa81..1dc234f5232b132ccda3d7a5d636de636ac958a6 100755 (executable)
@@ -39,7 +39,7 @@ if __name__ == "__main__":
     f = sys.stdout if use_stdout else open(outfile, "w")
     # mnemonic -> (library code, error prefix, header file)
     error_libraries = {}
-    for error_header in glob.glob(os.path.join(openssl_inc, 'include/openssl/*err.h')):
+    for error_header in glob.glob(os.path.join(glob.escape(openssl_inc), 'include/openssl/*err.h')):
         base = os.path.basename(error_header)
         if base in ('buffererr.h', 'objectserr.h', 'storeerr.h'):
             # Deprecated in 3.0.
index b220f5279ca63240fac6d23b2b4fe0a5ec0b791f..648e4e6a8932e7b73e8fa1ec5accab4c65ff865d 100644 (file)
--- a/setup.py
+++ b/setup.py
@@ -8,7 +8,7 @@ import os
 import re
 import sys
 import sysconfig
-from glob import glob
+from glob import glob, escape
 
 
 try:
@@ -401,7 +401,7 @@ class PyBuildExt(build_ext):
 
         # Python header files
         headers = [sysconfig.get_config_h_filename()]
-        headers += glob(os.path.join(sysconfig.get_path('include'), "*.h"))
+        headers += glob(os.path.join(escape(sysconfig.get_path('include')), "*.h"))
 
         for ext in self.extensions:
             ext.sources = [ find_module_file(filename, moddirlist)
@@ -2431,7 +2431,7 @@ class PyBuildExt(build_ext):
 
         if "blake2" in configured:
             blake2_deps = glob(
-                os.path.join(self.srcdir, 'Modules/_blake2/impl/*')
+                os.path.join(escape(self.srcdir), 'Modules/_blake2/impl/*')
             )
             blake2_deps.append('hashlib.h')
             self.add(Extension(
@@ -2446,7 +2446,7 @@ class PyBuildExt(build_ext):
 
         if "sha3" in configured:
             sha3_deps = glob(
-                os.path.join(self.srcdir, 'Modules/_sha3/kcp/*')
+                os.path.join(escape(self.srcdir), 'Modules/_sha3/kcp/*')
             )
             sha3_deps.append('hashlib.h')
             self.add(Extension(