bpo-41043: Escape literal part of the path for glob(). (GH-20994)
This commit is contained in:
parent
a041e116db
commit
9355868458
|
@ -5,7 +5,7 @@ Implements the Distutils 'build_py' command."""
|
||||||
import os
|
import os
|
||||||
import importlib.util
|
import importlib.util
|
||||||
import sys
|
import sys
|
||||||
from glob import glob
|
import glob
|
||||||
|
|
||||||
from distutils.core import Command
|
from distutils.core import Command
|
||||||
from distutils.errors import *
|
from distutils.errors import *
|
||||||
|
@ -125,7 +125,7 @@ class build_py (Command):
|
||||||
files = []
|
files = []
|
||||||
for pattern in globs:
|
for pattern in globs:
|
||||||
# Each pattern has to be converted to a platform-specific path
|
# 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 that match more than one pattern are only added once
|
||||||
files.extend([fn for fn in filelist if fn not in files
|
files.extend([fn for fn in filelist if fn not in files
|
||||||
and os.path.isfile(fn)])
|
and os.path.isfile(fn)])
|
||||||
|
@ -216,7 +216,7 @@ class build_py (Command):
|
||||||
|
|
||||||
def find_package_modules(self, package, package_dir):
|
def find_package_modules(self, package, package_dir):
|
||||||
self.check_package(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 = []
|
modules = []
|
||||||
setup_script = os.path.abspath(self.distribution.script_name)
|
setup_script = os.path.abspath(self.distribution.script_name)
|
||||||
|
|
||||||
|
|
|
@ -38,7 +38,7 @@ def listicons(icondir=ICONDIR):
|
||||||
"""Utility to display the available icons."""
|
"""Utility to display the available icons."""
|
||||||
root = Tk()
|
root = Tk()
|
||||||
import glob
|
import glob
|
||||||
list = glob.glob(os.path.join(icondir, "*.gif"))
|
list = glob.glob(os.path.join(glob.escape(icondir), "*.gif"))
|
||||||
list.sort()
|
list.sort()
|
||||||
images = []
|
images = []
|
||||||
row = column = 0
|
row = column = 0
|
||||||
|
|
|
@ -152,7 +152,7 @@ def testall(list, recursive, toplevel):
|
||||||
if recursive or toplevel:
|
if recursive or toplevel:
|
||||||
print('recursing down:')
|
print('recursing down:')
|
||||||
import glob
|
import glob
|
||||||
names = glob.glob(os.path.join(filename, '*'))
|
names = glob.glob(os.path.join(glob.escape(filename), '*'))
|
||||||
testall(names, recursive, 0)
|
testall(names, recursive, 0)
|
||||||
else:
|
else:
|
||||||
print('*** directory (use -r) ***')
|
print('*** directory (use -r) ***')
|
||||||
|
|
|
@ -473,7 +473,7 @@ class Pdb(bdb.Bdb, cmd.Cmd):
|
||||||
except Exception:
|
except Exception:
|
||||||
ret = []
|
ret = []
|
||||||
# Then, try to complete file names as well.
|
# Then, try to complete file names as well.
|
||||||
globs = glob.glob(text + '*')
|
globs = glob.glob(glob.escape(text) + '*')
|
||||||
for fn in globs:
|
for fn in globs:
|
||||||
if os.path.isdir(fn):
|
if os.path.isdir(fn):
|
||||||
ret.append(fn + '/')
|
ret.append(fn + '/')
|
||||||
|
|
|
@ -241,7 +241,7 @@ def testall(list, recursive, toplevel):
|
||||||
if recursive or toplevel:
|
if recursive or toplevel:
|
||||||
print('recursing down:')
|
print('recursing down:')
|
||||||
import glob
|
import glob
|
||||||
names = glob.glob(os.path.join(filename, '*'))
|
names = glob.glob(os.path.join(glob.escape(filename), '*'))
|
||||||
testall(names, recursive, 0)
|
testall(names, recursive, 0)
|
||||||
else:
|
else:
|
||||||
print('*** directory (use -r) ***')
|
print('*** directory (use -r) ***')
|
||||||
|
|
|
@ -4260,7 +4260,7 @@ class _TestImportStar(unittest.TestCase):
|
||||||
def get_module_names(self):
|
def get_module_names(self):
|
||||||
import glob
|
import glob
|
||||||
folder = os.path.dirname(multiprocessing.__file__)
|
folder = os.path.dirname(multiprocessing.__file__)
|
||||||
pattern = os.path.join(folder, '*.py')
|
pattern = os.path.join(glob.escape(folder), '*.py')
|
||||||
files = glob.glob(pattern)
|
files = glob.glob(pattern)
|
||||||
modules = [os.path.splitext(os.path.split(f)[1])[0] for f in files]
|
modules = [os.path.splitext(os.path.split(f)[1])[0] for f in files]
|
||||||
modules = ['multiprocessing.' + m for m in modules]
|
modules = ['multiprocessing.' + m for m in modules]
|
||||||
|
|
|
@ -602,7 +602,7 @@ class Regrtest:
|
||||||
def cleanup(self):
|
def cleanup(self):
|
||||||
import glob
|
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)
|
print("Cleanup %s directory" % self.tmp_dir)
|
||||||
for name in glob.glob(path):
|
for name in glob.glob(path):
|
||||||
if os.path.isdir(name):
|
if os.path.isdir(name):
|
||||||
|
|
|
@ -1345,7 +1345,7 @@ class PythonSymlink:
|
||||||
dll,
|
dll,
|
||||||
os.path.join(dest_dir, os.path.basename(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((
|
self._also_link.append((
|
||||||
runtime,
|
runtime,
|
||||||
os.path.join(dest_dir, os.path.basename(runtime))
|
os.path.join(dest_dir, os.path.basename(runtime))
|
||||||
|
|
|
@ -70,7 +70,7 @@ class BaseTest(unittest.TestCase):
|
||||||
# simply use the bigger test data for all tests.
|
# simply use the bigger test data for all tests.
|
||||||
test_size = 0
|
test_size = 0
|
||||||
BIG_TEXT = bytearray(128*1024)
|
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:
|
with open(fname, 'rb') as fh:
|
||||||
test_size += fh.readinto(memoryview(BIG_TEXT)[test_size:])
|
test_size += fh.readinto(memoryview(BIG_TEXT)[test_size:])
|
||||||
if test_size > 128*1024:
|
if test_size > 128*1024:
|
||||||
|
|
|
@ -11,7 +11,7 @@ import test.support
|
||||||
from test.support.script_helper import assert_python_failure
|
from test.support.script_helper import assert_python_failure
|
||||||
|
|
||||||
CRASHER_DIR = os.path.join(os.path.dirname(__file__), "crashers")
|
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"]
|
infinite_loops = ["infinite_loop_re.py", "nasty_eq_vs_dict.py"]
|
||||||
|
|
||||||
|
|
|
@ -33,7 +33,7 @@ def dbm_iterator():
|
||||||
def delete_files():
|
def delete_files():
|
||||||
# we don't know the precise name the underlying database uses
|
# we don't know the precise name the underlying database uses
|
||||||
# so we use glob to locate all names
|
# 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)
|
test.support.unlink(f)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -486,7 +486,7 @@ class ImportTests(unittest.TestCase):
|
||||||
pyexe = os.path.join(tmp, os.path.basename(sys.executable))
|
pyexe = os.path.join(tmp, os.path.basename(sys.executable))
|
||||||
shutil.copy(sys.executable, pyexe)
|
shutil.copy(sys.executable, pyexe)
|
||||||
shutil.copy(dllname, tmp)
|
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(f, tmp)
|
||||||
|
|
||||||
shutil.copy(pydname, tmp2)
|
shutil.copy(pydname, tmp2)
|
||||||
|
|
|
@ -979,7 +979,7 @@ class _TestMboxMMDF(_TestSingleFile):
|
||||||
super().tearDown()
|
super().tearDown()
|
||||||
self._box.close()
|
self._box.close()
|
||||||
self._delete_recursively(self._path)
|
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)
|
support.unlink(lock_remnant)
|
||||||
|
|
||||||
def assertMailboxEmpty(self):
|
def assertMailboxEmpty(self):
|
||||||
|
@ -1311,7 +1311,7 @@ class TestBabyl(_TestSingleFile, unittest.TestCase):
|
||||||
super().tearDown()
|
super().tearDown()
|
||||||
self._box.close()
|
self._box.close()
|
||||||
self._delete_recursively(self._path)
|
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)
|
support.unlink(lock_remnant)
|
||||||
|
|
||||||
def test_labels(self):
|
def test_labels(self):
|
||||||
|
|
|
@ -556,7 +556,7 @@ class CheckActualTests(BaseTestCase):
|
||||||
args = ['-Wd', '-E', '-bb', '-m', 'test.regrtest', '--list-tests']
|
args = ['-Wd', '-E', '-bb', '-m', 'test.regrtest', '--list-tests']
|
||||||
output = self.run_python(args)
|
output = self.run_python(args)
|
||||||
rough_number_of_tests_found = len(output.splitlines())
|
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')
|
'test*.py')
|
||||||
rough_counted_test_py_files = len(glob.glob(actual_testsuite_glob))
|
rough_counted_test_py_files = len(glob.glob(actual_testsuite_glob))
|
||||||
# We're not trying to duplicate test finding logic in here,
|
# We're not trying to duplicate test finding logic in here,
|
||||||
|
|
|
@ -543,7 +543,7 @@ class StartupImportTests(unittest.TestCase):
|
||||||
# found in sys.path (see site.addpackage()). Skip the test if at least
|
# found in sys.path (see site.addpackage()). Skip the test if at least
|
||||||
# one .pth file is found.
|
# one .pth file is found.
|
||||||
for path in isolated_paths:
|
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:
|
if pth_files:
|
||||||
self.skipTest(f"found {len(pth_files)} .pth files in: {path}")
|
self.skipTest(f"found {len(pth_files)} .pth files in: {path}")
|
||||||
|
|
||||||
|
|
|
@ -1605,7 +1605,7 @@ class TestRoundtrip(TestCase):
|
||||||
import glob, random
|
import glob, random
|
||||||
fn = support.findfile("tokenize_tests.txt")
|
fn = support.findfile("tokenize_tests.txt")
|
||||||
tempdir = os.path.dirname(fn) or os.curdir
|
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
|
# Tokenize is broken on test_pep3131.py because regular expressions are
|
||||||
# broken on the obscure unicode identifiers in it. *sigh*
|
# broken on the obscure unicode identifiers in it. *sigh*
|
||||||
|
|
|
@ -41,7 +41,7 @@ class TestUnicodeFiles(unittest.TestCase):
|
||||||
self._do_copyish(filename, filename)
|
self._do_copyish(filename, filename)
|
||||||
# Filename should appear in glob output
|
# Filename should appear in glob output
|
||||||
self.assertTrue(
|
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.
|
# basename should appear in listdir.
|
||||||
path, base = os.path.split(os.path.abspath(filename))
|
path, base = os.path.split(os.path.abspath(filename))
|
||||||
file_list = os.listdir(path)
|
file_list = os.listdir(path)
|
||||||
|
|
|
@ -413,7 +413,7 @@ class Grail(BaseBrowser):
|
||||||
tempdir = os.path.join(tempfile.gettempdir(),
|
tempdir = os.path.join(tempfile.gettempdir(),
|
||||||
".grail-unix")
|
".grail-unix")
|
||||||
user = pwd.getpwuid(os.getuid())[0]
|
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)
|
maybes = glob.glob(filename)
|
||||||
if not maybes:
|
if not maybes:
|
||||||
return None
|
return None
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
Fixed the use of :func:`~glob.glob` in the stdlib: literal part of the path
|
||||||
|
is now always correctly escaped.
|
|
@ -41,6 +41,8 @@ def walk_tree(root, *,
|
||||||
def glob_tree(root, *,
|
def glob_tree(root, *,
|
||||||
suffix=None,
|
suffix=None,
|
||||||
_glob=glob.iglob,
|
_glob=glob.iglob,
|
||||||
|
_escape=glob.escape,
|
||||||
|
_join=os.path.join,
|
||||||
):
|
):
|
||||||
"""Yield each file in the tree under the given directory name.
|
"""Yield each file in the tree under the given directory name.
|
||||||
|
|
||||||
|
@ -51,9 +53,9 @@ def glob_tree(root, *,
|
||||||
if not isinstance(suffix, str):
|
if not isinstance(suffix, str):
|
||||||
raise ValueError('suffix must be a string')
|
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
|
yield filename
|
||||||
for filename in _glob(f'{root}/**/*{suffix}'):
|
for filename in _glob(_join(_escape(root), f'**/*{suffix}')):
|
||||||
yield filename
|
yield filename
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -37,7 +37,9 @@ IGNORED_VARS = {
|
||||||
def find_capi_vars(root):
|
def find_capi_vars(root):
|
||||||
capi_vars = {}
|
capi_vars = {}
|
||||||
for dirname in SOURCE_DIRS:
|
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):
|
recursive=True):
|
||||||
with open(filename) as file:
|
with open(filename) as file:
|
||||||
for name in _find_capi_vars(file):
|
for name in _find_capi_vars(file):
|
||||||
|
|
|
@ -7,7 +7,7 @@ import sys
|
||||||
import time
|
import time
|
||||||
import traceback
|
import traceback
|
||||||
import tokenize
|
import tokenize
|
||||||
from glob import glob
|
from glob import glob, escape
|
||||||
from pathlib import PurePath
|
from pathlib import PurePath
|
||||||
|
|
||||||
from typing import List, Optional, Any, Tuple
|
from typing import List, Optional, Any, Tuple
|
||||||
|
@ -109,7 +109,7 @@ def parse_directory(directory: str, verbose: bool, excluded_files: List[str], sh
|
||||||
files = []
|
files = []
|
||||||
total_seconds = 0
|
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
|
# Only attempt to parse Python files and files that are not excluded
|
||||||
if any(PurePath(file).match(pattern) for pattern in excluded_files):
|
if any(PurePath(file).match(pattern) for pattern in excluded_files):
|
||||||
continue
|
continue
|
||||||
|
|
|
@ -39,7 +39,7 @@ if __name__ == "__main__":
|
||||||
f = sys.stdout if use_stdout else open(outfile, "w")
|
f = sys.stdout if use_stdout else open(outfile, "w")
|
||||||
# mnemonic -> (library code, error prefix, header file)
|
# mnemonic -> (library code, error prefix, header file)
|
||||||
error_libraries = {}
|
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)
|
base = os.path.basename(error_header)
|
||||||
if base in ('buffererr.h', 'objectserr.h', 'storeerr.h'):
|
if base in ('buffererr.h', 'objectserr.h', 'storeerr.h'):
|
||||||
# Deprecated in 3.0.
|
# Deprecated in 3.0.
|
||||||
|
|
8
setup.py
8
setup.py
|
@ -8,7 +8,7 @@ import os
|
||||||
import re
|
import re
|
||||||
import sys
|
import sys
|
||||||
import sysconfig
|
import sysconfig
|
||||||
from glob import glob
|
from glob import glob, escape
|
||||||
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
@ -401,7 +401,7 @@ class PyBuildExt(build_ext):
|
||||||
|
|
||||||
# Python header files
|
# Python header files
|
||||||
headers = [sysconfig.get_config_h_filename()]
|
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:
|
for ext in self.extensions:
|
||||||
ext.sources = [ find_module_file(filename, moddirlist)
|
ext.sources = [ find_module_file(filename, moddirlist)
|
||||||
|
@ -2431,7 +2431,7 @@ class PyBuildExt(build_ext):
|
||||||
|
|
||||||
if "blake2" in configured:
|
if "blake2" in configured:
|
||||||
blake2_deps = glob(
|
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')
|
blake2_deps.append('hashlib.h')
|
||||||
self.add(Extension(
|
self.add(Extension(
|
||||||
|
@ -2446,7 +2446,7 @@ class PyBuildExt(build_ext):
|
||||||
|
|
||||||
if "sha3" in configured:
|
if "sha3" in configured:
|
||||||
sha3_deps = glob(
|
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')
|
sha3_deps.append('hashlib.h')
|
||||||
self.add(Extension(
|
self.add(Extension(
|
||||||
|
|
Loading…
Reference in New Issue