Skip to content

Commit

Permalink
[Validator] reject ill-formed strings
Browse files Browse the repository at this point in the history
  • Loading branch information
nicolas-grekas committed Jan 28, 2015
1 parent faaa4fe commit 3a9058a
Show file tree
Hide file tree
Showing 5 changed files with 83 additions and 42 deletions.
1 change: 1 addition & 0 deletions src/Symfony/Component/Validator/Constraints/Length.php
Expand Up @@ -27,6 +27,7 @@ class Length extends Constraint
public $maxMessage = 'This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less.';
public $minMessage = 'This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more.';
public $exactMessage = 'This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters.';
public $charsetMessage = 'This value does not match the expected {{ charset }} charset.';
public $max;
public $min;
public $charset = 'UTF-8';
Expand Down
21 changes: 19 additions & 2 deletions src/Symfony/Component/Validator/Constraints/LengthValidator.php
Expand Up @@ -34,23 +34,40 @@ public function validate($value, Constraint $constraint)
}

$stringValue = (string) $value;
$invalidCharset = false;

if ('UTF8' === $charset = strtoupper($constraint->charset)) {
$charset = 'UTF-8';
}

if (function_exists('iconv_strlen')) {
$length = iconv_strlen($stringValue, $constraint->charset);
$length = @iconv_strlen($stringValue, $constraint->charset);
$invalidCharset = false === $length;
} elseif (function_exists('mb_strlen')) {
$length = mb_strlen($stringValue, $constraint->charset);
if (mb_check_encoding($stringValue, $constraint->charset)) {
$length = mb_strlen($stringValue, $constraint->charset);
} else {
$invalidCharset = true;
}
} elseif ('UTF-8' !== $charset) {
$length = strlen($stringValue);
} elseif (!preg_match('//u', $stringValue)) {
$invalidCharset = true;
} elseif (function_exists('utf8_decode')) {
$length = strlen(utf8_decode($stringValue));
} else {
preg_replace('/./u', '', $stringValue, -1, $length);
}

if ($invalidCharset) {
$this->context->addViolation($constraint->charsetMessage, array(
'{{ value }}' => $this->formatValue($stringValue),
'{{ charset }}' => $constraint->charset,
), $value);

return;
}

if ($constraint->min == $constraint->max && $length != $constraint->min) {
$this->context->addViolation($constraint->exactMessage, array(
'{{ value }}' => $this->formatValue($stringValue),
Expand Down
Expand Up @@ -278,6 +278,10 @@
<source>This value should not be identical to {{ compared_value_type }} {{ compared_value }}.</source>
<target>This value should not be identical to {{ compared_value_type }} {{ compared_value }}.</target>
</trans-unit>
<trans-unit id="73">
<source>This value does not match the expected {{ charset }} charset.</source>
<target>This value does not match the expected {{ charset }} charset.</target>
</trans-unit>
</body>
</file>
</xliff>
Expand Up @@ -278,6 +278,10 @@
<source>This value should not be identical to {{ compared_value_type }} {{ compared_value }}.</source>
<target>Cette valeur ne doit pas être identique à {{ compared_value_type }} {{ compared_value }}.</target>
</trans-unit>
<trans-unit id="73">
<source>This value does not match the expected {{ charset }} charset.</source>
<target>Cette valeur ne correspond pas au jeu de caractères {{ charset }} attendu.</target>
</trans-unit>
</body>
</file>
</xliff>
Expand Up @@ -48,12 +48,12 @@ public function getThreeOrLessCharacters()
return array(
array(12),
array('12'),
array('üü', true),
array('éé', true),
array('üü'),
array('éé'),
array(123),
array('123'),
array('üüü', true),
array('ééé', true),
array('üüü'),
array('ééé'),
);
}

Expand All @@ -62,8 +62,8 @@ public function getFourCharacters()
return array(
array(1234),
array('1234'),
array('üüüü', true),
array('éééé', true),
array('üüüü'),
array('éééé'),
);
}

Expand All @@ -80,24 +80,34 @@ public function getFiveOrMoreCharacters()
return array(
array(12345),
array('12345'),
array('üüüüü', true),
array('ééééé', true),
array('üüüüü'),
array('ééééé'),
array(123456),
array('123456'),
array('üüüüüü', true),
array('éééééé', true),
array('üüüüüü'),
array('éééééé'),
);
}

public function getOneCharset()
{
if (!function_exists('iconv') && !function_exists('mb_convert_encoding')) {
$this->markTestSkipped('Mbstring or iconv is required for this test.');
}

return array(
array("é", "utf8", true),
array("\xE9", "CP1252", true),
array("\xE9", "XXX", false),
array("\xE9", "utf8", false),
);
}

/**
* @dataProvider getFiveOrMoreCharacters
*/
public function testValidValuesMin($value, $mbOnly = false)
public function testValidValuesMin($value)
{
if ($mbOnly && !function_exists('mb_strlen')) {
$this->markTestSkipped('mb_strlen does not exist');
}

$constraint = new Length(array('min' => 5));
$this->validator->validate($value, $constraint);

Expand All @@ -107,12 +117,8 @@ public function testValidValuesMin($value, $mbOnly = false)
/**
* @dataProvider getThreeOrLessCharacters
*/
public function testValidValuesMax($value, $mbOnly = false)
public function testValidValuesMax($value)
{
if ($mbOnly && !function_exists('mb_strlen')) {
$this->markTestSkipped('mb_strlen does not exist');
}

$constraint = new Length(array('max' => 3));
$this->validator->validate($value, $constraint);

Expand All @@ -122,12 +128,8 @@ public function testValidValuesMax($value, $mbOnly = false)
/**
* @dataProvider getFourCharacters
*/
public function testValidValuesExact($value, $mbOnly = false)
public function testValidValuesExact($value)
{
if ($mbOnly && !function_exists('mb_strlen')) {
$this->markTestSkipped('mb_strlen does not exist');
}

$constraint = new Length(4);
$this->validator->validate($value, $constraint);

Expand All @@ -137,12 +139,8 @@ public function testValidValuesExact($value, $mbOnly = false)
/**
* @dataProvider getThreeOrLessCharacters
*/
public function testInvalidValuesMin($value, $mbOnly = false)
public function testInvalidValuesMin($value)
{
if ($mbOnly && !function_exists('mb_strlen')) {
$this->markTestSkipped('mb_strlen does not exist');
}

$constraint = new Length(array(
'min' => 4,
'minMessage' => 'myMessage',
Expand All @@ -161,12 +159,8 @@ public function testInvalidValuesMin($value, $mbOnly = false)
/**
* @dataProvider getFiveOrMoreCharacters
*/
public function testInvalidValuesMax($value, $mbOnly = false)
public function testInvalidValuesMax($value)
{
if ($mbOnly && !function_exists('mb_strlen')) {
$this->markTestSkipped('mb_strlen does not exist');
}

$constraint = new Length(array(
'max' => 4,
'maxMessage' => 'myMessage',
Expand All @@ -185,12 +179,8 @@ public function testInvalidValuesMax($value, $mbOnly = false)
/**
* @dataProvider getNotFourCharacters
*/
public function testInvalidValuesExact($value, $mbOnly = false)
public function testInvalidValuesExact($value)
{
if ($mbOnly && !function_exists('mb_strlen')) {
$this->markTestSkipped('mb_strlen does not exist');
}

$constraint = new Length(array(
'min' => 4,
'max' => 4,
Expand All @@ -207,6 +197,31 @@ public function testInvalidValuesExact($value, $mbOnly = false)
->assertRaised();
}

/**
* @dataProvider getOneCharset
*/
public function testOneCharset($value, $charset, $isValid)
{
$constraint = new Length(array(
'min' => 1,
'max' => 1,
'charset' => $charset,
'charsetMessage' => 'myMessage',
));

$this->validator->validate($value, $constraint);

if ($isValid) {
$this->assertNoViolation();
} else {
$this->buildViolation('myMessage')
->setParameter('{{ value }}', '"'.$value.'"')
->setParameter('{{ charset }}', $charset)
->setInvalidValue($value)
->assertRaised();
}
}

public function testConstraintGetDefaultOption()
{
$constraint = new Length(5);
Expand Down

0 comments on commit 3a9058a

Please sign in to comment.