From cfcaa85b81233d364defb1dc2afdd236dbd55059 Mon Sep 17 00:00:00 2001 From: Dominik Rumian Date: Feb 08 2022 10:37:54 +0000 Subject: Fix: Extra arguments now use shell-escaping Fixes splitting extra arguments on whitespaces. Extra arguments are converted to their shell-escaped version. JIRA: RHELCMP-7350 Fixes: https://pagure.io/rpkg/issue/587 Signed-off-by: Dominik Rumian --- diff --git a/pyrpkg/__init__.py b/pyrpkg/__init__.py index 3bc1829..7c03f45 100644 --- a/pyrpkg/__init__.py +++ b/pyrpkg/__init__.py @@ -22,6 +22,7 @@ import os import posixpath import random import re +import shlex import shutil import subprocess import sys @@ -1525,6 +1526,19 @@ class Commands(object): self._run_command(cmd, cwd=self.path) return + def process_extra_args(self, cmd, extra_args, cmd_name='rpmbuild'): + """Ensures that extra args are escaped in shell-compatible way + + :param list cmd: rpm command + :param list extra_args: additional arguments that are passed to + the command. + :param string cmd_name: name of the command, used for debug log + """ + extra_args = list(map(lambda arg: shlex.quote(arg), extra_args)) + cmd.extend(extra_args) + self.log.debug("Extra args '{0}' are passed to {1} " + "command".format(extra_args, cmd_name)) + def clone(self, repo, path=None, branch=None, bare_dir=None, anon=False, target=None, depth=None, extra_args=None): """Clone a repo, optionally check out a specific branch. @@ -1581,9 +1595,7 @@ class Commands(object): # --bare and --origin are incompatible cmd.extend(['--origin', self.default_branch_remote]) if extra_args: - cmd.extend(extra_args) - self.log.debug("Extra args '{0}' are passed to git clone " - "command".format(extra_args)) + self.process_extra_args(cmd, extra_args, 'git clone') if target: self.log.debug('Cloning into: %s', target) cmd.append(target) @@ -2543,9 +2555,7 @@ class Commands(object): for entry in define: cmd.extend(['--define', entry]) if extra_args: - cmd.extend(extra_args) - self.log.debug("Extra args '{0}' are passed to rpmbuild " - "command".format(extra_args)) + self.process_extra_args(cmd, extra_args) if short: cmd.append('--short-circuit') if nocheck: @@ -2619,9 +2629,7 @@ class Commands(object): for entry in define: cmd.extend(['--define', entry]) if extra_args: - cmd.extend(extra_args) - self.log.debug("Extra args '{0}' are passed to rpmbuild " - "command".format(extra_args)) + self.process_extra_args(cmd, extra_args) if short: cmd.append('--short-circuit') if nocheck: @@ -2753,9 +2761,7 @@ class Commands(object): for entry in define: cmd.extend(['--define', entry]) if extra_args: - cmd.extend(extra_args) - self.log.debug("Extra args '{0}' are passed to rpmbuild " - "command".format(extra_args)) + self.process_extra_args(cmd, extra_args) if self.quiet: cmd.append('--quiet') if buildrootdir: @@ -3137,9 +3143,7 @@ class Commands(object): for entry in define: cmd.extend(['--define', entry]) if extra_args: - cmd.extend(extra_args) - self.log.debug("Extra args '{0}' are passed to rpmbuild " - "command".format(extra_args)) + self.process_extra_args(cmd, extra_args) if self.quiet: cmd.append('--quiet') if buildrootdir: @@ -3186,9 +3190,7 @@ class Commands(object): for entry in define: cmd.extend(['--define', entry]) if extra_args: - cmd.extend(extra_args) - self.log.debug("Extra args '{0}' are passed to rpmbuild " - "command".format(extra_args)) + self.process_extra_args(cmd, extra_args) if self.quiet: cmd.append('--quiet') if buildrootdir: @@ -3299,9 +3301,7 @@ class Commands(object): for entry in define: cmd.extend(['--define', entry]) if extra_args: - cmd.extend(extra_args) - self.log.debug("Extra args '{0}' are passed to rpmbuild " - "command".format(extra_args)) + self.process_extra_args(cmd, extra_args) if self.quiet: cmd.append('--quiet') if buildrootdir: diff --git a/tests/test_cli.py b/tests/test_cli.py index 0304a11..dd21a54 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -7,6 +7,7 @@ import hashlib import logging import os import re +import shlex import shutil import subprocess import sys @@ -618,7 +619,7 @@ class TestSrpm(CliTestCase): cli.srpm() expected_cmd = ['rpmbuild'] + cli.cmd.rpmdefines + \ - ['--define', '"name body"', '--undefine', 'python', '--nodeps', '-bs', + ['--define', shlex.quote('"name body"'), '--undefine', 'python', '--nodeps', '-bs', os.path.join(cli.cmd.path, cli.cmd.spec)] _run_command.assert_called_once_with(expected_cmd, shell=True) @@ -700,6 +701,24 @@ class TestPrep(CliTestCase): ] _run_command.assert_called_once_with(rpmbuild, shell=True) + @patch('pyrpkg.Commands._run_command') + def test_prep_extra_args_with_space(self, _run_command): + first_arg_with_space = 'first with space' + second_arg_with_space = 'second with space' + cli_cmd = ['rpkg', '--path', self.cloned_repo_path, '--release', 'rhel-8', 'prep', '--', + '--define', first_arg_with_space, second_arg_with_space] + + with patch('sys.argv', new=cli_cmd): + cli = self.new_cli() + cli.prep() + + spec = os.path.join(cli.cmd.path, cli.cmd.spec) + rpmbuild = ['rpmbuild'] + cli.cmd.rpmdefines + ['--define', + shlex.quote(first_arg_with_space), + shlex.quote(second_arg_with_space), + '--nodeps', '-bp', spec] + _run_command.assert_called_once_with(rpmbuild, shell=True) + class TestInstall(CliTestCase):