Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 3d5d922

Browse files
[JsonPath] Handle slice selector overflow
1 parent 42171a1 commit 3d5d922

File tree

3 files changed

+74
-28
lines changed

3 files changed

+74
-28
lines changed

src/Symfony/Component/JsonPath/JsonCrawler.php

Lines changed: 44 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,10 @@ private function evaluateBracket(string $expr, mixed $value): array
143143

144144
// single negative index
145145
if (preg_match('/^-\d+$/', $expr)) {
146+
if (JsonPathUtils::hasLeadingZero($expr) || JsonPathUtils::isIntegerOverflow($expr) || '-0' === $expr) {
147+
throw new JsonCrawlerException($expr, 'invalid index selector');
148+
}
149+
146150
if (!array_is_list($value)) {
147151
return [];
148152
}
@@ -154,6 +158,12 @@ private function evaluateBracket(string $expr, mixed $value): array
154158

155159
// start and end index
156160
if (preg_match('/^-?\d+(?:\s*,\s*-?\d+)*$/', $expr)) {
161+
foreach (explode(',', $expr) as $exprPart) {
162+
if (JsonPathUtils::hasLeadingZero($exprPart = trim($exprPart)) || JsonPathUtils::isIntegerOverflow($exprPart) || '-0' === $exprPart) {
163+
throw new JsonCrawlerException($expr, 'invalid index selector');
164+
}
165+
}
166+
157167
if (!array_is_list($value)) {
158168
return [];
159169
}
@@ -172,17 +182,41 @@ private function evaluateBracket(string $expr, mixed $value): array
172182
return $result;
173183
}
174184

175-
if (preg_match('/^(-?\d*+)\s*+:\s*+(-?\d*+)(?:\s*+:\s*+(-?\d++))?$/', $expr, $matches)) {
185+
if (preg_match('/^(-?\d*+)\s*+:\s*+(-?\d*+)(?:\s*+:\s*+(-?\d*+))?$/', $expr, $matches)) {
176186
if (!array_is_list($value)) {
177187
return [];
178188
}
179189

190+
$startStr = trim($matches[1]);
191+
$endStr = trim($matches[2]);
192+
$stepStr = trim($matches[3] ?? '1');
193+
194+
if (
195+
JsonPathUtils::hasLeadingZero($startStr)
196+
|| JsonPathUtils::hasLeadingZero($endStr)
197+
|| JsonPathUtils::hasLeadingZero($stepStr)
198+
) {
199+
throw new JsonCrawlerException($expr, 'slice selector numbers cannot have leading zeros');
200+
}
201+
202+
if ('-0' === $startStr || '-0' === $endStr || '-0' === $stepStr) {
203+
throw new JsonCrawlerException($expr, 'slice selector cannot contain negative zero');
204+
}
205+
206+
if (
207+
JsonPathUtils::isIntegerOverflow($startStr)
208+
|| JsonPathUtils::isIntegerOverflow($endStr)
209+
|| JsonPathUtils::isIntegerOverflow($stepStr)
210+
) {
211+
throw new JsonCrawlerException($expr, 'slice selector integer overflow');
212+
}
213+
180214
$length = \count($value);
181-
$start = '' !== $matches[1] ? (int) $matches[1] : null;
182-
$end = '' !== $matches[2] ? (int) $matches[2] : null;
183-
$step = isset($matches[3]) && '' !== $matches[3] ? (int) $matches[3] : 1;
215+
$start = '' !== $startStr ? (int) $startStr : null;
216+
$end = '' !== $endStr ? (int) $endStr : null;
217+
$step = '' !== $stepStr ? (int) $stepStr : 1;
184218

185-
if (0 === $step || $start > $length) {
219+
if (0 === $step) {
186220
return [];
187221
}
188222

@@ -192,6 +226,11 @@ private function evaluateBracket(string $expr, mixed $value): array
192226
if ($start < 0) {
193227
$start = $length + $start;
194228
}
229+
230+
if ($step > 0 && $start >= $length) {
231+
return [];
232+
}
233+
195234
$start = max(0, min($start, $length - 1));
196235
}
197236

src/Symfony/Component/JsonPath/JsonPathUtils.php

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -225,4 +225,34 @@ public static function parseCommaSeparatedValues(string $expr): array
225225

226226
return $parts;
227227
}
228+
229+
public static function hasLeadingZero(string $s): bool
230+
{
231+
if ('' === $s || str_starts_with($s, '-') && '' === $s = substr($s, 1)) {
232+
return false;
233+
}
234+
235+
return '0' === $s[0] && 1 < \strlen($s);
236+
}
237+
238+
/**
239+
* Safe integer range is [-(2^53) + 1, (2^53) - 1].
240+
*
241+
* @see https://datatracker.ietf.org/doc/rfc9535/, section 2.1
242+
*/
243+
public static function isIntegerOverflow(string $s): bool
244+
{
245+
if ('' === $s) {
246+
return false;
247+
}
248+
249+
if (\strlen($s) > (str_starts_with($s, '-') ? 17 : 16)) {
250+
// obviously too long to represent anything in the interval
251+
return true;
252+
}
253+
254+
$value = (int) $s;
255+
256+
return $value < (-9007199254740991) || 9007199254740991 < $value;
257+
}
228258
}

src/Symfony/Component/JsonPath/Tests/JsonPathComplianceTestSuiteTest.php

Lines changed: 0 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -103,11 +103,6 @@ final class JsonPathComplianceTestSuiteTest extends TestCase
103103
'filter, group terms, right',
104104
'name selector, double quotes, escaped reverse solidus',
105105
'name selector, single quotes, escaped reverse solidus',
106-
'slice selector, slice selector with everything omitted, long form',
107-
'slice selector, start, min exact',
108-
'slice selector, start, max exact',
109-
'slice selector, end, min exact',
110-
'slice selector, end, max exact',
111106
'basic, descendant segment, multiple selectors',
112107
'basic, bald descendant segment',
113108
'filter, relative non-singular query, index, equal',
@@ -142,24 +137,6 @@ final class JsonPathComplianceTestSuiteTest extends TestCase
142137
'filter, absolute non-singular query, slice, less-or-equal',
143138
'filter, equals, special nothing',
144139
'filter, group terms, left',
145-
'index selector, min exact index - 1',
146-
'index selector, max exact index + 1',
147-
'index selector, overflowing index',
148-
'index selector, leading 0',
149-
'index selector, -0',
150-
'index selector, leading -0',
151-
'slice selector, excessively large from value with negative step',
152-
'slice selector, step, min exact - 1',
153-
'slice selector, step, max exact + 1',
154-
'slice selector, overflowing to value',
155-
'slice selector, underflowing from value',
156-
'slice selector, overflowing from value with negative step',
157-
'slice selector, underflowing to value with negative step',
158-
'slice selector, overflowing step',
159-
'slice selector, underflowing step',
160-
'slice selector, step, leading 0',
161-
'slice selector, step, -0',
162-
'slice selector, step, leading -0',
163140
];
164141

165142
/**

0 commit comments

Comments
 (0)