Skip to content

Commit

Permalink
[9.x] Ensure decimal rule handles large values (#45693)
Browse files Browse the repository at this point in the history
* Ensure decimal rule handles large values

* Refactor

* Remove todos

* lint
  • Loading branch information
timacdonald authored Jan 23, 2023
1 parent afccc6a commit da078c0
Show file tree
Hide file tree
Showing 2 changed files with 104 additions and 15 deletions.
32 changes: 17 additions & 15 deletions src/Illuminate/Validation/Concerns/ValidatesAttributes.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
namespace Illuminate\Validation\Concerns;

use Brick\Math\BigDecimal;
use Brick\Math\BigNumber;
use Brick\Math\Exception\MathException as BrickMathException;
use DateTime;
use DateTimeInterface;
Expand Down Expand Up @@ -436,9 +437,10 @@ public function validateBetween($attribute, $value, $parameters)
{
$this->requireParameterCount(2, $parameters, 'between');

$size = $this->getSize($attribute, $value);

return $size >= $parameters[0] && $size <= $parameters[1];
return with(
BigNumber::of($this->getSize($attribute, $value)),
fn ($size) => $size->isGreaterThanOrEqualTo($parameters[0]) && $size->isLessThanOrEqualTo($parameters[1])
);
}

/**
Expand Down Expand Up @@ -1080,15 +1082,15 @@ public function validateGt($attribute, $value, $parameters)
$this->shouldBeNumeric($attribute, 'Gt');

if (is_null($comparedToValue) && (is_numeric($value) && is_numeric($parameters[0]))) {
return $this->getSize($attribute, $value) > $parameters[0];
return BigNumber::of($this->getSize($attribute, $value))->isGreaterThan($parameters[0]);
}

if (is_numeric($parameters[0])) {
return false;
}

if ($this->hasRule($attribute, $this->numericRules) && is_numeric($value) && is_numeric($comparedToValue)) {
return $value > $comparedToValue;
return BigNumber::of($value)->isGreaterThan($comparedToValue);
}

if (! $this->isSameType($value, $comparedToValue)) {
Expand All @@ -1115,15 +1117,15 @@ public function validateLt($attribute, $value, $parameters)
$this->shouldBeNumeric($attribute, 'Lt');

if (is_null($comparedToValue) && (is_numeric($value) && is_numeric($parameters[0]))) {
return $this->getSize($attribute, $value) < $parameters[0];
return BigNumber::of($this->getSize($attribute, $value))->isLessThan($parameters[0]);
}

if (is_numeric($parameters[0])) {
return false;
}

if ($this->hasRule($attribute, $this->numericRules) && is_numeric($value) && is_numeric($comparedToValue)) {
return $value < $comparedToValue;
return BigNumber::of($value)->isLessThan($comparedToValue);
}

if (! $this->isSameType($value, $comparedToValue)) {
Expand All @@ -1150,15 +1152,15 @@ public function validateGte($attribute, $value, $parameters)
$this->shouldBeNumeric($attribute, 'Gte');

if (is_null($comparedToValue) && (is_numeric($value) && is_numeric($parameters[0]))) {
return $this->getSize($attribute, $value) >= $parameters[0];
return BigNumber::of($this->getSize($attribute, $value))->isGreaterThanOrEqualTo($parameters[0]);
}

if (is_numeric($parameters[0])) {
return false;
}

if ($this->hasRule($attribute, $this->numericRules) && is_numeric($value) && is_numeric($comparedToValue)) {
return $value >= $comparedToValue;
return BigNumber::of($value)->isGreaterThanOrEqualTo($comparedToValue);
}

if (! $this->isSameType($value, $comparedToValue)) {
Expand All @@ -1185,15 +1187,15 @@ public function validateLte($attribute, $value, $parameters)
$this->shouldBeNumeric($attribute, 'Lte');

if (is_null($comparedToValue) && (is_numeric($value) && is_numeric($parameters[0]))) {
return $this->getSize($attribute, $value) <= $parameters[0];
return BigNumber::of($this->getSize($attribute, $value))->isLessThanOrEqualTo($parameters[0]);
}

if (is_numeric($parameters[0])) {
return false;
}

if ($this->hasRule($attribute, $this->numericRules) && is_numeric($value) && is_numeric($comparedToValue)) {
return $value <= $comparedToValue;
return BigNumber::of($value)->isLessThanOrEqualTo($comparedToValue);
}

if (! $this->isSameType($value, $comparedToValue)) {
Expand Down Expand Up @@ -1385,7 +1387,7 @@ public function validateMax($attribute, $value, $parameters)
return false;
}

return $this->getSize($attribute, $value) <= $parameters[0];
return BigNumber::of($this->getSize($attribute, $value))->isLessThanOrEqualTo($parameters[0]);
}

/**
Expand Down Expand Up @@ -1487,7 +1489,7 @@ public function validateMin($attribute, $value, $parameters)
{
$this->requireParameterCount(1, $parameters, 'min');

return $this->getSize($attribute, $value) >= $parameters[0];
return BigNumber::of($this->getSize($attribute, $value))->isGreaterThanOrEqualTo($parameters[0]);
}

/**
Expand Down Expand Up @@ -2162,7 +2164,7 @@ public function validateSize($attribute, $value, $parameters)
{
$this->requireParameterCount(1, $parameters, 'size');

return $this->getSize($attribute, $value) == $parameters[0];
return BigNumber::of($this->getSize($attribute, $value))->isEqualTo($parameters[0]);
}

/**
Expand Down Expand Up @@ -2321,7 +2323,7 @@ public function validateUuid($attribute, $value)
*
* @param string $attribute
* @param mixed $value
* @return mixed
* @return int|float|string
*/
protected function getSize($attribute, $value)
{
Expand Down
87 changes: 87 additions & 0 deletions tests/Validation/ValidationValidatorTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -2767,6 +2767,93 @@ public function testValidateDecimal()

$v = new Validator($trans, ['foo' => '1.23'], ['foo' => 'Decimal:0,1']);
$this->assertFalse($v->passes());

$v = new Validator($trans, ['foo' => '1.8888888888'], ['foo' => 'Decimal:10']);
$this->assertTrue($v->passes());

$v = new Validator($trans, ['foo' => '1.88888888888888888888'], ['foo' => 'Decimal:20']);
$this->assertTrue($v->passes());

$v = new Validator($trans, ['foo' => '1.88888888888888888888'], ['foo' => 'Decimal:20|Min:1.88888888888888888889']);
$this->assertFalse($v->passes());

$v = new Validator($trans, ['foo' => '1.88888888888888888888'], ['foo' => 'Decimal:20|Min:1.88888888888888888888']);
$this->assertTrue($v->passes());

$v = new Validator($trans, ['foo' => '1.88888888888888888888'], ['foo' => 'Decimal:20|Max:1.88888888888888888888']);
$this->assertTrue($v->passes());

$v = new Validator($trans, ['foo' => '1.88888888888888888888'], ['foo' => 'Decimal:20|Max:1.88888888888888888887']);
$this->assertFalse($v->passes());

$v = new Validator($trans, ['foo' => '1.88888888888888888888'], ['foo' => 'Decimal:20|Max:1.88888888888888888887']);
$this->assertFalse($v->passes());

$v = new Validator($trans, ['foo' => '1.88888888888888888888'], ['foo' => 'Decimal:20|Size:1.88888888888888888889']);
$this->assertFalse($v->passes());

$v = new Validator($trans, ['foo' => '1.88888888888888888888'], ['foo' => 'Decimal:20|Size:1.88888888888888888888']);
$this->assertTrue($v->passes());

$v = new Validator($trans, ['foo' => '1.88888888888888888889'], ['foo' => 'Decimal:20|Between:1.88888888888888888886,1.88888888888888888888']);
$this->assertFalse($v->passes());

$v = new Validator($trans, ['foo' => '1.88888888888888888887'], ['foo' => 'Decimal:20|Between:1.88888888888888888886,1.88888888888888888888']);
$this->assertTrue($v->passes());

$v = new Validator($trans, ['foo' => '1.88888888888888888888'], ['foo' => 'Decimal:20|Gt:1.88888888888888888888']);
$this->assertFalse($v->passes());

$v = new Validator($trans, ['foo' => '1.88888888888888888889'], ['foo' => 'Decimal:20|Gt:1.88888888888888888888']);
$this->assertTrue($v->passes());

$v = new Validator($trans, ['foo' => '1.88888888888888888888', 'bar' => '1.88888888888888888888'], ['foo' => 'Decimal:20|Gt:bar']);
$this->assertFalse($v->passes());

$v = new Validator($trans, ['foo' => '1.88888888888888888889', 'bar' => '1.88888888888888888888'], ['foo' => 'Decimal:20|Gt:bar']);
$this->assertTrue($v->passes());

$v = new Validator($trans, ['foo' => '1.88888888888888888888'], ['foo' => 'Decimal:20|Lt:1.88888888888888888888']);
$this->assertFalse($v->passes());

$v = new Validator($trans, ['foo' => '1.88888888888888888887'], ['foo' => 'Decimal:20|Lt:1.88888888888888888888']);
$this->assertTrue($v->passes());

$v = new Validator($trans, ['foo' => '1.88888888888888888888', 'bar' => '1.88888888888888888888'], ['foo' => 'Decimal:20|Lt:bar']);
$this->assertFalse($v->passes());

$v = new Validator($trans, ['foo' => '1.88888888888888888887', 'bar' => '1.88888888888888888888'], ['foo' => 'Decimal:20|Lt:bar']);
$this->assertTrue($v->passes());

$v = new Validator($trans, ['foo' => '1.88888888888888888887'], ['foo' => 'Decimal:20|Gte:1.88888888888888888888']);
$this->assertFalse($v->passes());

$v = new Validator($trans, ['foo' => '1.88888888888888888888'], ['foo' => 'Decimal:20|Gte:1.88888888888888888888']);
$this->assertTrue($v->passes());

$v = new Validator($trans, ['foo' => '1.88888888888888888887', 'bar' => '1.88888888888888888888'], ['foo' => 'Decimal:20|Gte:bar']);
$this->assertFalse($v->passes());

$v = new Validator($trans, ['foo' => '1.88888888888888888888', 'bar' => '1.88888888888888888888'], ['foo' => 'Decimal:20|Gte:bar']);
$this->assertTrue($v->passes());

$v = new Validator($trans, ['foo' => '1.88888888888888888889'], ['foo' => 'Decimal:20|Lte:1.88888888888888888888']);
$this->assertFalse($v->passes());

$v = new Validator($trans, ['foo' => '1.88888888888888888888'], ['foo' => 'Decimal:20|Lte:1.88888888888888888888']);
$this->assertTrue($v->passes());

$v = new Validator($trans, ['foo' => '1.88888888888888888889', 'bar' => '1.88888888888888888888'], ['foo' => 'Decimal:20|Lte:bar']);
$this->assertFalse($v->passes());

$v = new Validator($trans, ['foo' => '1.88888888888888888888', 'bar' => '1.88888888888888888888'], ['foo' => 'Decimal:20|Lte:bar']);
$this->assertTrue($v->passes());

$v = new Validator($trans, ['foo' => '1.88888888888888888889'], ['foo' => 'Decimal:20|Max:1.88888888888888888888']);
$this->assertFalse($v->passes());

$v = new Validator($trans, ['foo' => '1.88888888888888888888'], ['foo' => 'Decimal:20|Max:1.88888888888888888888']);
$this->assertTrue($v->passes());
}

public function testValidateInt()
Expand Down

0 comments on commit da078c0

Please sign in to comment.