From 9606f5a63fb9c91536a6d417da6967ef4939fe1f Mon Sep 17 00:00:00 2001 From: Owais Date: Thu, 20 Dec 2018 19:53:03 +0500 Subject: [PATCH 1/5] feat(attribute_value): Don't target NAN, INF, -INF and > 2^53 --- src/Optimizely/Utils/Validator.php | 38 ++++++++++++++++++++++++++++-- tests/UtilsTests/ValidatorTest.php | 27 +++++++++++++++++++++ 2 files changed, 63 insertions(+), 2 deletions(-) diff --git a/src/Optimizely/Utils/Validator.php b/src/Optimizely/Utils/Validator.php index 5b8dd7e0..085cb979 100644 --- a/src/Optimizely/Utils/Validator.php +++ b/src/Optimizely/Utils/Validator.php @@ -79,8 +79,42 @@ public static function areAttributesValid($attributes) */ public static function isAttributeValid($attributeKey, $attributeValue) { - $validTypes = array('boolean', 'double', 'integer', 'string'); - return is_string($attributeKey) && in_array(gettype($attributeValue), $validTypes); + if (!is_string($attributeKey)) { + return false; + } + + if (is_string($attributeValue) || is_bool($attributeValue)) { + return true; + } + + if (is_int($attributeValue) || is_float($attributeValue)) { + return Validator::isFiniteNumber($attributeValue); + } + + return false; + } + + /** + * @param $value The value to validate. + * + * @return boolean Representing whether attribute's value is + * a number and not NAN, INF, -INF or greater than 2^53. + */ + public static function isFiniteNumber($value) + { + if (!(is_int($value) || is_float($value))) { + return false; + } + + if (is_nan($value) || is_infinite($value)) { + return false; + } + + if (abs($value) > (2**53)) { + return false; + } + + return true; } /** diff --git a/tests/UtilsTests/ValidatorTest.php b/tests/UtilsTests/ValidatorTest.php index 715b54a9..43dae6eb 100644 --- a/tests/UtilsTests/ValidatorTest.php +++ b/tests/UtilsTests/ValidatorTest.php @@ -123,6 +123,33 @@ public function testisAttributeValidAttributeWithInValidKeyValue() $this->assertFalse(Validator::isAttributeValid(5.5, 'value')); } + public function testIsFiniteNumberWithInvalidValues() + { + $this->assertFalse(Validator::IsFiniteNumber('HelloWorld')); + $this->assertFalse(Validator::IsFiniteNumber(true)); + $this->assertFalse(Validator::IsFiniteNumber(false)); + $this->assertFalse(Validator::IsFiniteNumber(null)); + $this->assertFalse(Validator::IsFiniteNumber((object)[])); + $this->assertFalse(Validator::IsFiniteNumber([])); + $this->assertFalse(Validator::IsFiniteNumber(INF)); + $this->assertFalse(Validator::IsFiniteNumber(-INF)); + $this->assertFalse(Validator::IsFiniteNumber(NAN)); + $this->assertFalse(Validator::IsFiniteNumber((2**53) + 1)); + $this->assertFalse(Validator::IsFiniteNumber(-(2**53) - 1)); + $this->assertFalse(Validator::IsFiniteNumber((2**53) + 2.0)); + $this->assertFalse(Validator::IsFiniteNumber(-(2**53) - 2.0)); + } + + public function testIsFiniteNumberWithValidValues() + { + $this->assertTrue(Validator::IsFiniteNumber(0)); + $this->assertTrue(Validator::IsFiniteNumber(5)); + $this->assertTrue(Validator::IsFiniteNumber(5.5)); + $this->assertTrue(Validator::IsFiniteNumber((2**53) + 1.0)); + $this->assertTrue(Validator::IsFiniteNumber(-(2**53) - 1.0)); + $this->assertTrue(Validator::IsFiniteNumber((2**53))); + } + public function testAreEventTagsValidValidEventTags() { // Empty attributes From 0de41d301561fc1a040f5c0a896face005e84aa1 Mon Sep 17 00:00:00 2001 From: Owais Date: Thu, 20 Dec 2018 20:01:34 +0500 Subject: [PATCH 2/5] ** operator not supported on PHP 5.5 --- tests/UtilsTests/ValidatorTest.php | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/tests/UtilsTests/ValidatorTest.php b/tests/UtilsTests/ValidatorTest.php index 43dae6eb..08d78886 100644 --- a/tests/UtilsTests/ValidatorTest.php +++ b/tests/UtilsTests/ValidatorTest.php @@ -134,10 +134,10 @@ public function testIsFiniteNumberWithInvalidValues() $this->assertFalse(Validator::IsFiniteNumber(INF)); $this->assertFalse(Validator::IsFiniteNumber(-INF)); $this->assertFalse(Validator::IsFiniteNumber(NAN)); - $this->assertFalse(Validator::IsFiniteNumber((2**53) + 1)); - $this->assertFalse(Validator::IsFiniteNumber(-(2**53) - 1)); - $this->assertFalse(Validator::IsFiniteNumber((2**53) + 2.0)); - $this->assertFalse(Validator::IsFiniteNumber(-(2**53) - 2.0)); + $this->assertFalse(Validator::IsFiniteNumber(pow(2,53) + 1)); + $this->assertFalse(Validator::IsFiniteNumber(-pow(2,53) - 1)); + $this->assertFalse(Validator::IsFiniteNumber(pow(2,53) + 2.0)); + $this->assertFalse(Validator::IsFiniteNumber(-pow(2,53) - 2.0)); } public function testIsFiniteNumberWithValidValues() @@ -145,9 +145,9 @@ public function testIsFiniteNumberWithValidValues() $this->assertTrue(Validator::IsFiniteNumber(0)); $this->assertTrue(Validator::IsFiniteNumber(5)); $this->assertTrue(Validator::IsFiniteNumber(5.5)); - $this->assertTrue(Validator::IsFiniteNumber((2**53) + 1.0)); - $this->assertTrue(Validator::IsFiniteNumber(-(2**53) - 1.0)); - $this->assertTrue(Validator::IsFiniteNumber((2**53))); + $this->assertTrue(Validator::IsFiniteNumber(pow(2,53) + 1.0)); + $this->assertTrue(Validator::IsFiniteNumber(-pow(2,53) - 1.0)); + $this->assertTrue(Validator::IsFiniteNumber(pow(2,53))); } public function testAreEventTagsValidValidEventTags() From c64797c78e6c1acdd4b3adf3e5b3a10b35e16064 Mon Sep 17 00:00:00 2001 From: Owais Date: Thu, 20 Dec 2018 20:05:49 +0500 Subject: [PATCH 3/5] ** operator not supported in PHP 5.5 --- src/Optimizely/Utils/Validator.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Optimizely/Utils/Validator.php b/src/Optimizely/Utils/Validator.php index 085cb979..4356d3dd 100644 --- a/src/Optimizely/Utils/Validator.php +++ b/src/Optimizely/Utils/Validator.php @@ -110,7 +110,7 @@ public static function isFiniteNumber($value) return false; } - if (abs($value) > (2**53)) { + if (abs($value) > pow(2,53)) { return false; } From dee3468f46e462179e5c0769664d040eb9db1cec Mon Sep 17 00:00:00 2001 From: Owais Date: Fri, 21 Dec 2018 13:04:56 +0500 Subject: [PATCH 4/5] Add comment --- tests/UtilsTests/ValidatorTest.php | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/UtilsTests/ValidatorTest.php b/tests/UtilsTests/ValidatorTest.php index 08d78886..98fd6fef 100644 --- a/tests/UtilsTests/ValidatorTest.php +++ b/tests/UtilsTests/ValidatorTest.php @@ -145,6 +145,7 @@ public function testIsFiniteNumberWithValidValues() $this->assertTrue(Validator::IsFiniteNumber(0)); $this->assertTrue(Validator::IsFiniteNumber(5)); $this->assertTrue(Validator::IsFiniteNumber(5.5)); + // float(2**53) + 1.0 evaluates to float(2**53) $this->assertTrue(Validator::IsFiniteNumber(pow(2,53) + 1.0)); $this->assertTrue(Validator::IsFiniteNumber(-pow(2,53) - 1.0)); $this->assertTrue(Validator::IsFiniteNumber(pow(2,53))); From cf4057260ab46e606d4a8d5c8825a1298e685abe Mon Sep 17 00:00:00 2001 From: Owais Date: Mon, 24 Dec 2018 12:18:46 +0500 Subject: [PATCH 5/5] refact-nit --- src/Optimizely/Utils/Validator.php | 49 +++++++++++++++--------------- tests/UtilsTests/ValidatorTest.php | 2 +- 2 files changed, 26 insertions(+), 25 deletions(-) diff --git a/src/Optimizely/Utils/Validator.php b/src/Optimizely/Utils/Validator.php index 4356d3dd..7f10c2f1 100644 --- a/src/Optimizely/Utils/Validator.php +++ b/src/Optimizely/Utils/Validator.php @@ -70,12 +70,36 @@ public static function areAttributesValid($attributes) return count(array_filter(array_keys($attributes), 'is_string')) > 0; } + /** + * @param $value The value to validate. + * + * @return boolean Representing whether attribute's value is + * a number and not NAN, INF, -INF or greater than absolute limit of 2^53. + */ + public static function isFiniteNumber($value) + { + if (!(is_int($value) || is_float($value))) { + return false; + } + + if (is_nan($value) || is_infinite($value)) { + return false; + } + + if (abs($value) > pow(2, 53)) { + return false; + } + + return true; + } + /** * @param $attributeKey The key to validate. * @param $attributeValue The value to validate. * * @return boolean Representing whether attribute's key and value are - * valid for event payload or not. + * valid for event payload or not. Valid attribute key must be a string. + * Valid attribute value can be a string, bool, or a finite number. */ public static function isAttributeValid($attributeKey, $attributeValue) { @@ -94,29 +118,6 @@ public static function isAttributeValid($attributeKey, $attributeValue) return false; } - /** - * @param $value The value to validate. - * - * @return boolean Representing whether attribute's value is - * a number and not NAN, INF, -INF or greater than 2^53. - */ - public static function isFiniteNumber($value) - { - if (!(is_int($value) || is_float($value))) { - return false; - } - - if (is_nan($value) || is_infinite($value)) { - return false; - } - - if (abs($value) > pow(2,53)) { - return false; - } - - return true; - } - /** * @param $eventTags mixed Event tags to be validated. * diff --git a/tests/UtilsTests/ValidatorTest.php b/tests/UtilsTests/ValidatorTest.php index 98fd6fef..8ecf8e87 100644 --- a/tests/UtilsTests/ValidatorTest.php +++ b/tests/UtilsTests/ValidatorTest.php @@ -145,7 +145,7 @@ public function testIsFiniteNumberWithValidValues() $this->assertTrue(Validator::IsFiniteNumber(0)); $this->assertTrue(Validator::IsFiniteNumber(5)); $this->assertTrue(Validator::IsFiniteNumber(5.5)); - // float(2**53) + 1.0 evaluates to float(2**53) + // float pow(2,53) + 1.0 evaluates to float pow(2,53) $this->assertTrue(Validator::IsFiniteNumber(pow(2,53) + 1.0)); $this->assertTrue(Validator::IsFiniteNumber(-pow(2,53) - 1.0)); $this->assertTrue(Validator::IsFiniteNumber(pow(2,53)));