From 36009e3ca78cb92914e72a59633ea219d601fc4f Mon Sep 17 00:00:00 2001 From: Max Semenik Date: Tue, 28 Nov 2017 18:51:25 -0800 Subject: [PATCH] Shell: skip null parameters Right now they're treated as empty strings, however this doesn't allow skipping parameters in the middle like $params = [ 'foo', $x ? '--bar' : null, '--baz', ]; In some cases this matters, e.g. `ls` works while `ls ''` doesn't. Also, fix spacing problems the new tests uncovered: * Extra space when using params() * Missing space when combining params() and unsafeParams() Change-Id: Icb29d4c48ae7f92fb5635e3865346c98f47abb01 --- includes/shell/Command.php | 11 +++++++++-- includes/shell/Shell.php | 5 ++++- tests/phpunit/includes/shell/CommandTest.php | 11 +++++++++++ tests/phpunit/includes/shell/ShellTest.php | 1 + 4 files changed, 25 insertions(+), 3 deletions(-) diff --git a/includes/shell/Command.php b/includes/shell/Command.php index 264c3b48cc..998b3ed905 100644 --- a/includes/shell/Command.php +++ b/includes/shell/Command.php @@ -106,6 +106,7 @@ class Command { /** * Adds parameters to the command. All parameters are sanitized via Shell::escape(). + * Null values are ignored. * * @param string|string[] $args,... * @return $this @@ -117,13 +118,14 @@ class Command { // treat it as a list of arguments $args = reset( $args ); } - $this->command .= ' ' . Shell::escape( $args ); + $this->command = trim( $this->command . ' ' . Shell::escape( $args ) ); return $this; } /** * Adds unsafe parameters to the command. These parameters are NOT sanitized in any way. + * Null values are ignored. * * @param string|string[] $args,... * @return $this @@ -135,7 +137,12 @@ class Command { // treat it as a list of arguments $args = reset( $args ); } - $this->command .= implode( ' ', $args ); + $args = array_filter( $args, + function ( $value ) { + return $value !== null; + } + ); + $this->command = trim( $this->command . ' ' . implode( ' ', $args ) ); return $this; } diff --git a/includes/shell/Shell.php b/includes/shell/Shell.php index 6e4fd02a13..084e10e793 100644 --- a/includes/shell/Shell.php +++ b/includes/shell/Shell.php @@ -142,7 +142,7 @@ class Shell { * PHP 5.2.6+ (bug backported to earlier distro releases of PHP). * * @param string $args,... strings to escape and glue together, or a single array of - * strings parameter + * strings parameter. Null values are ignored. * @return string */ public static function escape( /* ... */ ) { @@ -156,6 +156,9 @@ class Shell { $first = true; $retVal = ''; foreach ( $args as $arg ) { + if ( $arg === null ) { + continue; + } if ( !$first ) { $retVal .= ' '; } else { diff --git a/tests/phpunit/includes/shell/CommandTest.php b/tests/phpunit/includes/shell/CommandTest.php index 81fae33c84..f7275e14e8 100644 --- a/tests/phpunit/includes/shell/CommandTest.php +++ b/tests/phpunit/includes/shell/CommandTest.php @@ -1,6 +1,7 @@ assertRegExp( '/^.+no-such-file.*$/m', $result->getStderr() ); } + /** + * Test that null values are skipped by params() and unsafeParams() + */ + public function testNullsAreSkipped() { + $command = TestingAccessWrapper::newFromObject( new Command ); + $command->params( 'echo', 'a', null, 'b' ); + $command->unsafeParams( 'c', null, 'd' ); + $this->assertEquals( "'echo' 'a' 'b' c d", $command->command ); + } + public function testT69870() { $commandLine = wfIsWindows() // 333 = 331 + CRLF diff --git a/tests/phpunit/includes/shell/ShellTest.php b/tests/phpunit/includes/shell/ShellTest.php index 1e91074fd4..7c96c3c856 100644 --- a/tests/phpunit/includes/shell/ShellTest.php +++ b/tests/phpunit/includes/shell/ShellTest.php @@ -25,6 +25,7 @@ class ShellTest extends PHPUnit_Framework_TestCase { 'simple' => [ [ 'true' ], "'true'" ], 'with args' => [ [ 'convert', '-font', 'font name' ], "'convert' '-font' 'font name'" ], 'array' => [ [ [ 'convert', '-font', 'font name' ] ], "'convert' '-font' 'font name'" ], + 'skip nulls' => [ [ 'ls', null ], "'ls'" ], ]; } } -- 2.20.1