Skip to content

[JsonPath] Improve compliance to the RFC test suite #60699

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: 7.3
Choose a base branch
from

Conversation

alexandre-daubois
Copy link
Member

@alexandre-daubois alexandre-daubois commented Jun 5, 2025

Q A
Branch? 7.3
Bug fix? yes
New feature? no
Deprecations? no
Issues -
License MIT

This PR is a big step forward on making the component RFC compliant. Many more tests are now green as you can see in the JsonPathComplianceTestSuiteTest. Mainly, it's about dealing with whitespaces, better expressions parsing and supporting ! and bare literals like true, false and null.

@carsonbot carsonbot added this to the 7.3 milestone Jun 5, 2025
@alexandre-daubois alexandre-daubois changed the title [JsonPath] Handle special whitespaces in filters [JsonPath] Handle special whitespaces in expressions Jun 5, 2025
@alexandre-daubois
Copy link
Member Author

Thank you @stof, I didn't know that denial of service was actually a thing with regex. I updated accordingly.

@stof
Copy link
Member

stof commented Jun 5, 2025

@alexandre-daubois this can be a thing when you allow user input for the string being matched by the regex (which could totally happen in this component). Backtracking engines (like PCRE) have an exponential complexity based on the length of the input when attempting to match an affected regex (and failing to match it, as this is the worse case of backtracking).

This is commonly reported in the npm ecosystem (also because JS does not support possessive quantifiers in its Regexp syntax, and so cannot apply the easy fix to prevent them in many cases, making the issue more common)

@alexandre-daubois
Copy link
Member Author

Applied your suggestions, it makes the code a bit simpler. Thanks!

@alexandre-daubois alexandre-daubois changed the title [JsonPath] Handle special whitespaces in expressions [JsonPath] Improve compliance to the RFC test suite Jun 13, 2025
@alexandre-daubois
Copy link
Member Author

alexandre-daubois commented Jun 13, 2025

I reworked the whole PR to keep pushing forward the compliance test suite. This PR removes 265 skips, so that's pretty nice.

Status: Needs Review

@alexandre-daubois alexandre-daubois force-pushed the jsonpath-blankspaces branch 2 times, most recently from d71e0e5 to 84193ab Compare June 13, 2025 14:57
Comment on lines +326 to +339
if (str_starts_with($expr, '(') && str_ends_with($expr, ')')) {
$depth = 0;
$isWrapped = true;
for ($i = 0; $i < strlen($expr); $i++) {
if ($expr[$i] === '(') {
$depth++;
} elseif ($expr[$i] === ')') {
$depth--;
if ($depth === 0 && $i < strlen($expr) - 1) {
$isWrapped = false;
break;
}
}
}
Copy link
Member

@nicolas-grekas nicolas-grekas Jun 15, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

/cc @fabpot we have an issue with fabbot:

Suggested change
if (str_starts_with($expr, '(') && str_ends_with($expr, ')')) {
$depth = 0;
$isWrapped = true;
for ($i = 0; $i < strlen($expr); $i++) {
if ($expr[$i] === '(') {
$depth++;
} elseif ($expr[$i] === ')') {
$depth--;
if ($depth === 0 && $i < strlen($expr) - 1) {
$isWrapped = false;
break;
}
}
}
if (str_starts_with($expr, '(') && str_ends_with($expr, ')')) {
$depth = 0;
$isWrapped = true;
for ($i = 0; $i < \strlen($expr); ++$i) {
if ('(' === $expr[$i]) {
++$depth;
} elseif (')' === $expr[$i]) {
--$depth;
if (0 === $depth && $i < \strlen($expr) - 1) {
$isWrapped = false;
break;
}
}
}

Comment on lines +476 to +478
} else {
$pathPart = substr($arg, 1);
if (str_starts_with($pathPart, '[')) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
} else {
$pathPart = substr($arg, 1);
if (str_starts_with($pathPart, '[')) {
} elseif (str_starts_with($pathPart = substr($arg, 1), '[')) {

$args = $this->parseCommaSeparatedValues($args);
foreach ($args as $arg) {
$arg = trim($arg);
if (str_starts_with($arg, '@')) { // special handling for @ to track nodelist size
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this will reduce the nesting level:

Suggested change
if (str_starts_with($arg, '@')) { // special handling for @ to track nodelist size
if (str_starts_with($arg, '$')) { // special handling for absolute paths
}elseif (!str_starts_with($arg, '@')) {
//[...]

continue;
}

if ($char === '\\') {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yoda style everywhere

doesn't running php-cs-fixer locally catch those?


if (preg_match('/\b(match|search)\s*\(([^)]*)\)/', $filterExpr, $matches)) {
$args = trim($matches[2]);
if (empty($args)) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

empty

if (preg_match('/\b(length|count|value)\s*\(([^)]*)\)/', $filterExpr, $matches)) {
$functionName = $matches[1];
$args = trim($matches[2]);
if (empty($args)) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please remove all usages of empty from the PR

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants