Fixes for module param counting and additional shell quoting issues

pull/8275/head
James Cammarata 10 years ago
parent 091b76efaa
commit 2cc602beea

@ -389,7 +389,7 @@ class Runner(object):
return actual_user return actual_user
def _count_module_args(self, args): def _count_module_args(self, args, allow_dupes=False):
''' '''
Count the number of k=v pairs in the supplied module args. This is Count the number of k=v pairs in the supplied module args. This is
basically a specialized version of parse_kv() from utils with a few basically a specialized version of parse_kv() from utils with a few
@ -399,23 +399,26 @@ class Runner(object):
if args is not None: if args is not None:
args = args.encode('utf-8') args = args.encode('utf-8')
try: try:
lexer = shlex.shlex(args, posix=True) lexer = shlex.shlex(args)
lexer.whitespace = '\t '
lexer.whitespace_split = True lexer.whitespace_split = True
lexer.quotes = '"' vargs = [x.decode('utf-8') for x in lexer]
lexer.ignore_quotes = "'"
vargs = list(lexer)
except ValueError, ve: except ValueError, ve:
if 'no closing quotation' in str(ve).lower(): if 'no closing quotation' in str(ve).lower():
raise errors.AnsibleError("error parsing argument string '%s', try quoting the entire line." % args) raise errors.AnsibleError("error parsing argument string '%s', try quoting the entire line." % args)
else: else:
raise raise
vargs = [x.decode('utf-8') for x in vargs]
for x in vargs: for x in vargs:
if "=" in x: quoted = x.startswith('"') and x.endswith('"') or x.startswith("'") and x.endswith("'")
if "=" in x and not quoted:
k, v = x.split("=",1) k, v = x.split("=",1)
if k in options: is_shell_module = self.module_name in ('command', 'shell')
raise errors.AnsibleError("a duplicate parameter was found in the argument string (%s)" % k) is_shell_param = k in ('creates', 'removes', 'chdir', 'executable')
options[k] = v if k in options and not allow_dupes:
if not(is_shell_module and not is_shell_param):
raise errors.AnsibleError("a duplicate parameter was found in the argument string (%s)" % k)
if is_shell_module and is_shell_param or not is_shell_module:
options[k] = v
return len(options) return len(options)
@ -863,7 +866,7 @@ class Runner(object):
# that no variables inadvertantly (or maliciously) add params # that no variables inadvertantly (or maliciously) add params
# to the list of args. We do this by counting the number of k=v # to the list of args. We do this by counting the number of k=v
# pairs before and after templating. # pairs before and after templating.
num_args_pre = self._count_module_args(module_args) num_args_pre = self._count_module_args(module_args, allow_dupes=True)
module_args = template.template(self.basedir, module_args, inject, fail_on_undefined=self.error_on_undefined_vars) module_args = template.template(self.basedir, module_args, inject, fail_on_undefined=self.error_on_undefined_vars)
num_args_post = self._count_module_args(module_args) num_args_post = self._count_module_args(module_args)
if num_args_pre != num_args_post: if num_args_pre != num_args_post:

@ -213,16 +213,21 @@ class CommandModule(AnsibleModule):
# use shlex to split up the args, while being careful to preserve # use shlex to split up the args, while being careful to preserve
# single quotes so they're not removed accidentally # single quotes so they're not removed accidentally
lexer = shlex.shlex(args, posix=True) lexer = shlex.shlex(args)
lexer.whitespace = '\t '
lexer.whitespace_split = True lexer.whitespace_split = True
lexer.quotes = '"'
lexer.ignore_quotes = "'"
items = list(lexer) items = list(lexer)
for x in items: for x in items:
if '=' in x: quoted = x.startswith('"') and x.endswith('"') or x.startswith("'") and x.endswith("'")
if '=' in x and not quoted:
# check to see if this is a special parameter for the command # check to see if this is a special parameter for the command
k, v = x.split('=', 1) k, v = x.split('=', 1)
# because we're not breaking out quotes in the shlex split
# above, the value of the k=v pair may still be quoted. If
# so, remove them.
if len(v) > 1 and (v.startswith('"') and v.endswith('"') or v.startswith("'") and v.endswith("'")):
v = v[1:-1]
if k in ('creates', 'removes', 'chdir', 'executable', 'NO_LOG'): if k in ('creates', 'removes', 'chdir', 'executable', 'NO_LOG'):
if k == "chdir": if k == "chdir":
v = os.path.abspath(os.path.expanduser(v)) v = os.path.abspath(os.path.expanduser(v))
@ -235,7 +240,7 @@ class CommandModule(AnsibleModule):
params[k] = v params[k] = v
# Remove any of the above k=v params from the args string # Remove any of the above k=v params from the args string
args = PARAM_REGEX.sub('', args) args = PARAM_REGEX.sub('', args)
params['args'] = args params['args'] = args.strip()
return (params, params['args']) return (params, params['args'])
main() main()

Loading…
Cancel
Save