[controller ansiballz] escape directory regex (#74270)

Change:
- We were passing a directory name directly to re.compile().
  If the directory isn't valid regex (or is) this can have odd side
  effects, such as crashing.
- Fix a few other similar cases, but less likely to be a real issue.

Test Plan:
- New test

Signed-off-by: Rick Elrod <rick@elrod.me>
pull/74291/head
Rick Elrod 3 years ago committed by GitHub
parent cf4a9fcd0f
commit 7ef3dc2b8b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -0,0 +1,4 @@
bugfixes:
- >-
ansiballz - avoid treating path to site_packages as regex; escape it.
This prevents a crash when ansible is installed to, or running from, an oddly named directory like ``ansi[ble``

@ -417,7 +417,7 @@ else:
# Do this instead of getting site-packages from distutils.sysconfig so we work when we
# haven't been installed
site_packages = os.path.dirname(os.path.dirname(os.path.dirname(__file__)))
CORE_LIBRARY_PATH_RE = re.compile(r'%s/(?P<path>ansible/modules/.*)\.(py|ps1)$' % site_packages)
CORE_LIBRARY_PATH_RE = re.compile(r'%s/(?P<path>ansible/modules/.*)\.(py|ps1)$' % re.escape(site_packages))
COLLECTION_PATH_RE = re.compile(r'/(?P<path>ansible_collections/[^/]+/[^/]+/plugins/modules/.*)\.(py|ps1)$')
# Detect new-style Python modules by looking for required imports:

@ -1173,7 +1173,8 @@ class ActionBase(with_metaclass(ABCMeta, object)):
# try to figure out if we are missing interpreter
if self._used_interpreter is not None:
match = re.compile('%s: (?:No such file or directory|not found)' % self._used_interpreter.lstrip('!#'))
interpreter = re.escape(self._used_interpreter.lstrip('!#'))
match = re.compile('%s: (?:No such file or directory|not found)' % interpreter)
if match.search(data['module_stderr']) or match.search(data['module_stdout']):
data['msg'] = "The module failed to execute correctly, you probably need to set the interpreter."

@ -133,7 +133,7 @@ def clean_facts(facts):
# next we remove any connection plugin specific vars
for conn_path in connection_loader.all(path_only=True):
conn_name = os.path.splitext(os.path.basename(conn_path))[0]
re_key = re.compile('^ansible_%s_' % conn_name)
re_key = re.compile('^ansible_%s_' % re.escape(conn_name))
for fact_key in fact_keys:
# most lightweight VM or container tech creates devices with this pattern, this avoids filtering them out
if (re_key.match(fact_key) and not fact_key.endswith(('_bridge', '_gwbridge'))) or fact_key.startswith('ansible_become_'):

@ -0,0 +1,15 @@
#!/usr/bin/env bash
# #74270 -- ensure we escape directory names before passing to re.compile()
# particularly in module_common.
set -eux
lib_path=$(python -c 'import os, ansible; print(os.path.dirname(os.path.dirname(ansible.__file__)))')
bad_dir="${OUTPUT_DIR}/ansi[ble"
mkdir "${bad_dir}"
cp -a "${lib_path}" "${bad_dir}"
PYTHONPATH="${bad_dir}/lib" ansible -m ping localhost -i ../../inventory "$@"
rm -rf "${bad_dir}"

@ -80,3 +80,7 @@ if ansible-playbook -i ../../inventory --extra-vars ./vars.yml playbook.yml; the
fi
ansible-playbook -i ../../inventory --extra-vars @./vars.yml playbook.yml
# #74270 -- ensure we escape directory names before passing to re.compile()
# particularly in module_common.
bash module_common_regex_regression.sh

Loading…
Cancel
Save