[Process] Add validation on Process input

This commit is contained in:
Romain Neutron 2014-05-17 19:27:19 +02:00
parent 735e9a4768
commit 583092b6da
5 changed files with 95 additions and 4 deletions

View File

@ -881,6 +881,7 @@ class Process
* @return self The current Process instance * @return self The current Process instance
* *
* @throws LogicException In case the process is running * @throws LogicException In case the process is running
* @throws InvalidArgumentException In case the argument is invalid
*/ */
public function setStdin($stdin) public function setStdin($stdin)
{ {
@ -888,7 +889,7 @@ class Process
throw new LogicException('STDIN can not be set while the process is running.'); throw new LogicException('STDIN can not be set while the process is running.');
} }
$this->stdin = $stdin; $this->stdin = ProcessUtils::validateInput(sprintf('%s::%s', __CLASS__, __FUNCTION__), $stdin);
return $this; return $this;
} }

View File

@ -148,13 +148,15 @@ class ProcessBuilder
/** /**
* Sets the input of the process. * Sets the input of the process.
* *
* @param string $stdin The input as a string * @param string|null $stdin The input as a string
* *
* @return ProcessBuilder * @return ProcessBuilder
*
* @throws InvalidArgumentException In case the argument is invalid
*/ */
public function setInput($stdin) public function setInput($stdin)
{ {
$this->stdin = $stdin; $this->stdin = ProcessUtils::validateInput(sprintf('%s::%s', __CLASS__, __FUNCTION__), $stdin);
return $this; return $this;
} }

View File

@ -11,6 +11,8 @@
namespace Symfony\Component\Process; namespace Symfony\Component\Process;
use Symfony\Component\Process\Exception\InvalidArgumentException;
/** /**
* ProcessUtils is a bunch of utility methods. * ProcessUtils is a bunch of utility methods.
* *
@ -72,6 +74,29 @@ class ProcessUtils
return escapeshellarg($argument); return escapeshellarg($argument);
} }
/**
* Validates and normalized a Process input
*
* @param string $caller The name of method call that validates the input
* @param mixed $input The input to validate
*
* @return string The validated input
*
* @throws InvalidArgumentException In case the input is not valid
*/
public static function validateInput($caller, $input)
{
if (null !== $input) {
if (is_scalar($input) || (is_object($input) && method_exists($input, '__toString'))) {
return (string) $input;
}
throw new InvalidArgumentException(sprintf('%s only accepts strings.', $caller));
}
return $input;
}
private static function isSurroundedBy($arg, $char) private static function isSurroundedBy($arg, $char)
{ {
return 2 < strlen($arg) && $char === $arg[0] && $char === $arg[strlen($arg) - 1]; return 2 < strlen($arg) && $char === $arg[0] && $char === $arg[strlen($arg) - 1];

View File

@ -171,6 +171,47 @@ abstract class AbstractProcessTest extends \PHPUnit_Framework_TestCase
$process->stop(); $process->stop();
} }
/**
* @dataProvider provideInvalidStdinValues
* @expectedException \Symfony\Component\Process\Exception\InvalidArgumentException
* @expectedExceptionMessage Symfony\Component\Process\Process::setStdin only accepts strings.
*/
public function testInvalidStdin($value)
{
$process = $this->getProcess('php -v');
$process->setStdin($value);
}
public function provideInvalidStdinValues()
{
return array(
array(array()),
array(new NonStringifiable()),
array(fopen('php://temporary', 'w')),
);
}
/**
* @dataProvider provideStdinValues
*/
public function testValidStdin($expected, $value)
{
$process = $this->getProcess('php -v');
$process->setStdin($value);
$this->assertSame($expected, $process->getStdin());
}
public function provideStdinValues()
{
return array(
array(null, null),
array('24.5', 24.5),
array('input data', 'input data'),
// to maintain BC, supposed to be removed in 3.0
array('stringifiable', new Stringifiable()),
);
}
public function chainedCommandsOutputProvider() public function chainedCommandsOutputProvider()
{ {
if (defined('PHP_WINDOWS_VERSION_BUILD')) { if (defined('PHP_WINDOWS_VERSION_BUILD')) {
@ -813,3 +854,15 @@ abstract class AbstractProcessTest extends \PHPUnit_Framework_TestCase
*/ */
abstract protected function getProcess($commandline, $cwd = null, array $env = null, $stdin = null, $timeout = 60, array $options = array()); abstract protected function getProcess($commandline, $cwd = null, array $env = null, $stdin = null, $timeout = 60, array $options = array());
} }
class Stringifiable
{
public function __toString()
{
return 'stringifiable';
}
}
class NonStringifiable
{
}

View File

@ -197,4 +197,14 @@ class ProcessBuilderTest extends \PHPUnit_Framework_TestCase
$this->assertEquals("'/usr/bin/php'", $process->getCommandLine()); $this->assertEquals("'/usr/bin/php'", $process->getCommandLine());
} }
} }
/**
* @expectedException \Symfony\Component\Process\Exception\InvalidArgumentException
* @expectedExceptionMessage Symfony\Component\Process\ProcessBuilder::setInput only accepts strings.
*/
public function testInvalidInput()
{
$builder = ProcessBuilder::create();
$builder->setInput(array());
}
} }