From da55e691256df731cfce0b800a61b4ff6634ac27 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Viktor=20Djupsj=C3=B6backa?= Date: Sun, 26 Jan 2025 02:34:21 +0200 Subject: [PATCH] Allow numeric strings in number comparisons --- src/jsonpath/interpreter.c | 9 ++- tests/024.phpt | 93 ++++++++++++++++++++++++ tests/025.phpt | 121 +++++++++++++++++++++++++++++++ tests/026.phpt | 93 ++++++++++++++++++++++++ tests/comparison_filter/047.phpt | 7 +- tests/comparison_filter/048.phpt | 12 ++- tests/comparison_filter/051.phpt | 7 +- tests/comparison_filter/052.phpt | 12 ++- tests/comparison_filter/055.phpt | 9 +-- 9 files changed, 350 insertions(+), 13 deletions(-) create mode 100644 tests/024.phpt create mode 100644 tests/025.phpt create mode 100644 tests/026.phpt diff --git a/src/jsonpath/interpreter.c b/src/jsonpath/interpreter.c index fd6b735..78e4e10 100644 --- a/src/jsonpath/interpreter.c +++ b/src/jsonpath/interpreter.c @@ -528,8 +528,13 @@ static BOOL_OR_ERR evaluate_binary(zval* arr_head, zval* arr_cur, struct ast_nod /* Determine if two zvals can be checked for inequality (>, <, >=, <=). Specifically forbid comparing strings with * numeric values in order to avoid returning true for scenarios such as 42 > "value". */ static bool can_check_inequality(zval* lhs, zval* rhs) { - bool lhs_is_numeric = (Z_TYPE_P(lhs) == IS_LONG || Z_TYPE_P(lhs) == IS_DOUBLE); - bool rhs_is_numeric = (Z_TYPE_P(rhs) == IS_LONG || Z_TYPE_P(rhs) == IS_DOUBLE); + bool lhs_is_numeric = + (Z_TYPE_P(lhs) == IS_LONG || Z_TYPE_P(lhs) == IS_DOUBLE || + (Z_TYPE_P(lhs) == IS_STRING && is_numeric_string(Z_STRVAL_P(lhs), Z_STRLEN_P(lhs), NULL, NULL, 0))); + + bool rhs_is_numeric = + (Z_TYPE_P(rhs) == IS_LONG || Z_TYPE_P(rhs) == IS_DOUBLE || + (Z_TYPE_P(rhs) == IS_STRING && is_numeric_string(Z_STRVAL_P(rhs), Z_STRLEN_P(rhs), NULL, NULL, 0))); if (lhs_is_numeric && rhs_is_numeric) { return true; diff --git a/tests/024.phpt b/tests/024.phpt new file mode 100644 index 0000000..b70f6ad --- /dev/null +++ b/tests/024.phpt @@ -0,0 +1,93 @@ +--TEST-- +Test greater-than number comparison condition with integer compared to numbers and numerical strings +--SKIPIF-- + +--FILE-- + 'tomato', + 'quantity' => '4', + ], + [ + 'product' => 'apple', + 'quantity' => '1', + ], + [ + 'product' => 'pear', + 'quantity' => 2, + ], + [ + 'product' => 'banana', + 'quantity' => '0', + ], + [ + 'product' => 'cucumber', + 'quantity' => 0, + ], + [ + 'product' => 'coconut', + 'quantity' => '0.5', + ], + [ + 'product' => 'carrot', + 'quantity' => '3', + ], + [ + 'product' => 'cauliflower', + 'quantity' => '-4', + ], + [ + 'product' => 'watermelon', + 'quantity' => '-2', + ], + [ + 'product' => 'asparagus', + 'quantity' => '-2.5', + ], +]; + +$jsonPath = new \JsonPath\JsonPath(); +$result = $jsonPath->find($data, "$[?(@.quantity > 0)]"); + +var_dump($result); +?> +--EXPECT-- +array(5) { + [0]=> + array(2) { + ["product"]=> + string(6) "tomato" + ["quantity"]=> + string(1) "4" + } + [1]=> + array(2) { + ["product"]=> + string(5) "apple" + ["quantity"]=> + string(1) "1" + } + [2]=> + array(2) { + ["product"]=> + string(4) "pear" + ["quantity"]=> + int(2) + } + [3]=> + array(2) { + ["product"]=> + string(7) "coconut" + ["quantity"]=> + string(3) "0.5" + } + [4]=> + array(2) { + ["product"]=> + string(6) "carrot" + ["quantity"]=> + string(1) "3" + } +} diff --git a/tests/025.phpt b/tests/025.phpt new file mode 100644 index 0000000..77cb911 --- /dev/null +++ b/tests/025.phpt @@ -0,0 +1,121 @@ +--TEST-- +Test greater-than-or-equal-to number comparison condition with integer compared to numbers and numerical strings +--SKIPIF-- + +--FILE-- + 'tomato', + 'quantity' => '4', + ], + [ + 'product' => 'apple', + 'quantity' => '1', + ], + [ + 'product' => 'pear', + 'quantity' => 2, + ], + [ + 'product' => 'banana', + 'quantity' => '0', + ], + [ + 'product' => 'cucumber', + 'quantity' => 0, + ], + [ + 'product' => 'coconut', + 'quantity' => '0.5', + ], + [ + 'product' => 'carrot', + 'quantity' => '3', + ], + [ + 'product' => 'cauliflower', + 'quantity' => '-4', + ], + [ + 'product' => 'watermelon', + 'quantity' => '-2', + ], + [ + 'product' => 'asparagus', + 'quantity' => '-2.5', + ], +]; + +$jsonPath = new \JsonPath\JsonPath(); +$result = $jsonPath->find($data, "$[?(@.quantity >= -3)]"); + +var_dump($result); +?> +--EXPECT-- +array(9) { + [0]=> + array(2) { + ["product"]=> + string(6) "tomato" + ["quantity"]=> + string(1) "4" + } + [1]=> + array(2) { + ["product"]=> + string(5) "apple" + ["quantity"]=> + string(1) "1" + } + [2]=> + array(2) { + ["product"]=> + string(4) "pear" + ["quantity"]=> + int(2) + } + [3]=> + array(2) { + ["product"]=> + string(6) "banana" + ["quantity"]=> + string(1) "0" + } + [4]=> + array(2) { + ["product"]=> + string(8) "cucumber" + ["quantity"]=> + int(0) + } + [5]=> + array(2) { + ["product"]=> + string(7) "coconut" + ["quantity"]=> + string(3) "0.5" + } + [6]=> + array(2) { + ["product"]=> + string(6) "carrot" + ["quantity"]=> + string(1) "3" + } + [7]=> + array(2) { + ["product"]=> + string(10) "watermelon" + ["quantity"]=> + string(2) "-2" + } + [8]=> + array(2) { + ["product"]=> + string(9) "asparagus" + ["quantity"]=> + string(4) "-2.5" + } +} diff --git a/tests/026.phpt b/tests/026.phpt new file mode 100644 index 0000000..46b3191 --- /dev/null +++ b/tests/026.phpt @@ -0,0 +1,93 @@ +--TEST-- +Test greater-than number comparison condition with float compared to numbers and numerical strings +--SKIPIF-- + +--FILE-- + 'tomato', + 'quantity' => '4', + ], + [ + 'product' => 'apple', + 'quantity' => '1', + ], + [ + 'product' => 'pear', + 'quantity' => 2, + ], + [ + 'product' => 'banana', + 'quantity' => '0', + ], + [ + 'product' => 'cucumber', + 'quantity' => 0, + ], + [ + 'product' => 'coconut', + 'quantity' => '0.5', + ], + [ + 'product' => 'carrot', + 'quantity' => '3', + ], + [ + 'product' => 'cauliflower', + 'quantity' => '-4', + ], + [ + 'product' => 'watermelon', + 'quantity' => '-2', + ], + [ + 'product' => 'asparagus', + 'quantity' => '-2.5', + ], +]; + +$jsonPath = new \JsonPath\JsonPath(); +$result = $jsonPath->find($data, "$[?(@.quantity > 0.2)]"); + +var_dump($result); +?> +--EXPECT-- +array(5) { + [0]=> + array(2) { + ["product"]=> + string(6) "tomato" + ["quantity"]=> + string(1) "4" + } + [1]=> + array(2) { + ["product"]=> + string(5) "apple" + ["quantity"]=> + string(1) "1" + } + [2]=> + array(2) { + ["product"]=> + string(4) "pear" + ["quantity"]=> + int(2) + } + [3]=> + array(2) { + ["product"]=> + string(7) "coconut" + ["quantity"]=> + string(3) "0.5" + } + [4]=> + array(2) { + ["product"]=> + string(6) "carrot" + ["quantity"]=> + string(1) "3" + } +} diff --git a/tests/comparison_filter/047.phpt b/tests/comparison_filter/047.phpt index 30c1e7f..b19efff 100644 --- a/tests/comparison_filter/047.phpt +++ b/tests/comparison_filter/047.phpt @@ -53,7 +53,7 @@ $result = $jsonPath->find($data, "$[?(@.key>42)]"); var_dump($result); ?> --EXPECT-- -array(3) { +array(4) { [0]=> array(1) { ["key"]=> @@ -69,4 +69,9 @@ array(3) { ["key"]=> int(100) } + [3]=> + array(1) { + ["key"]=> + string(2) "43" + } } \ No newline at end of file diff --git a/tests/comparison_filter/048.phpt b/tests/comparison_filter/048.phpt index 514496a..9081890 100644 --- a/tests/comparison_filter/048.phpt +++ b/tests/comparison_filter/048.phpt @@ -53,7 +53,7 @@ $result = $jsonPath->find($data, "$[?(@.key>=42)]"); var_dump($result); ?> --EXPECT-- -array(4) { +array(6) { [0]=> array(1) { ["key"]=> @@ -74,4 +74,14 @@ array(4) { ["key"]=> int(100) } + [4]=> + array(1) { + ["key"]=> + string(2) "43" + } + [5]=> + array(1) { + ["key"]=> + string(2) "42" + } } \ No newline at end of file diff --git a/tests/comparison_filter/051.phpt b/tests/comparison_filter/051.phpt index 12257d5..1df0af2 100644 --- a/tests/comparison_filter/051.phpt +++ b/tests/comparison_filter/051.phpt @@ -53,7 +53,7 @@ $result = $jsonPath->find($data, "$[?(@.key<42)]"); var_dump($result); ?> --EXPECT-- -array(4) { +array(5) { [0]=> array(1) { ["key"]=> @@ -74,4 +74,9 @@ array(4) { ["key"]=> float(41.9999) } + [4]=> + array(1) { + ["key"]=> + string(2) "41" + } } \ No newline at end of file diff --git a/tests/comparison_filter/052.phpt b/tests/comparison_filter/052.phpt index 2dc0de7..6eadd81 100644 --- a/tests/comparison_filter/052.phpt +++ b/tests/comparison_filter/052.phpt @@ -53,7 +53,7 @@ $result = $jsonPath->find($data, "$[?(@.key<=42)]"); var_dump($result); ?> --EXPECT-- -array(5) { +array(7) { [0]=> array(1) { ["key"]=> @@ -79,4 +79,14 @@ array(5) { ["key"]=> float(41.9999) } + [5]=> + array(1) { + ["key"]=> + string(2) "42" + } + [6]=> + array(1) { + ["key"]=> + string(2) "41" + } } \ No newline at end of file diff --git a/tests/comparison_filter/055.phpt b/tests/comparison_filter/055.phpt index 917f07a..039dd10 100644 --- a/tests/comparison_filter/055.phpt +++ b/tests/comparison_filter/055.phpt @@ -53,7 +53,7 @@ $result = $jsonPath->find($data, "$[?(!(@.key<42))]"); var_dump($result); ?> --EXPECT-- -array(9) { +array(8) { [0]=> array(1) { ["key"]=> @@ -85,16 +85,11 @@ array(9) { string(2) "42" } [6]=> - array(1) { - ["key"]=> - string(2) "41" - } - [7]=> array(1) { ["key"]=> string(5) "value" } - [8]=> + [7]=> array(1) { ["some"]=> string(5) "value"