Skip to content

Commit ed27476

Browse files
bug symfony#60802 [JsonPath] Improve escape sequence validation in name selector (alexandre-daubois)
This PR was merged into the 7.3 branch. Discussion ---------- [JsonPath] Improve escape sequence validation in name selector | Q | A | ------------- | --- | Branch? | 7.3 | Bug fix? | yes | New feature? | no | Deprecations? | no | Issues | - | License | MIT Commits ------- 7b08ef7 [JsonPath] Improve escape sequence validation in name selector
2 parents 7095ee9 + 7b08ef7 commit ed27476

File tree

3 files changed

+11
-64
lines changed

3 files changed

+11
-64
lines changed

src/Symfony/Component/JsonPath/JsonPathUtils.php

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
namespace Symfony\Component\JsonPath;
1313

1414
use Symfony\Component\JsonPath\Exception\InvalidArgumentException;
15+
use Symfony\Component\JsonPath\Exception\JsonCrawlerException;
1516
use Symfony\Component\JsonPath\Tokenizer\JsonPathToken;
1617
use Symfony\Component\JsonPath\Tokenizer\TokenType;
1718
use Symfony\Component\JsonStreamer\Read\Splitter;
@@ -86,6 +87,9 @@ public static function findSmallestDeserializableStringAndPath(array $tokens, mi
8687
];
8788
}
8889

90+
/**
91+
* @throws JsonCrawlerException When an invalid Unicode escape sequence occurs
92+
*/
8993
public static function unescapeString(string $str, string $quoteChar): string
9094
{
9195
if ('"' === $quoteChar) {
@@ -104,17 +108,16 @@ public static function unescapeString(string $str, string $quoteChar): string
104108
while (null !== $char = $str[++$i] ?? null) {
105109
if ('\\' === $char && isset($str[$i + 1])) {
106110
$result .= match ($str[$i + 1]) {
107-
'"' => '"',
108-
"'" => "'",
109111
'\\' => '\\',
110112
'/' => '/',
111-
'b' => "\b",
113+
'b' => "\x08",
112114
'f' => "\f",
113115
'n' => "\n",
114116
'r' => "\r",
115117
't' => "\t",
116118
'u' => self::unescapeUnicodeSequence($str, $i),
117-
default => $char.$str[$i + 1], // keep the backslash
119+
$quoteChar => $quoteChar,
120+
default => throw new JsonCrawlerException('', \sprintf('Invalid escape sequence "\\%s" in %s-quoted string', $str[$i + 1], "'" === $quoteChar ? 'single' : 'double')),
118121
};
119122

120123
++$i;
@@ -128,16 +131,11 @@ public static function unescapeString(string $str, string $quoteChar): string
128131

129132
private static function unescapeUnicodeSequence(string $str, int &$i): string
130133
{
131-
if (!isset($str[$i + 5])) {
132-
// not enough characters for Unicode escape, treat as literal
133-
return $str[$i];
134+
if (!isset($str[$i + 5]) || !ctype_xdigit(substr($str, $i + 2, 4))) {
135+
throw new JsonCrawlerException('', 'Invalid unicode escape sequence');
134136
}
135137

136138
$hex = substr($str, $i + 2, 4);
137-
if (!ctype_xdigit($hex)) {
138-
// invalid hex, treat as literal
139-
return $str[$i];
140-
}
141139

142140
$codepoint = hexdec($hex);
143141
// looks like a valid Unicode codepoint, string length is sufficient and it starts with \u

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

Lines changed: 2 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ public function testEscapedDoubleQuotesInFieldName()
8686
{"a": {"b\\"c": 42}}
8787
JSON);
8888

89-
$result = $crawler->find("$['a']['b\\\"c']");
89+
$result = $crawler->find('$["a"]["b\"c"]');
9090

9191
$this->assertSame(42, $result[0]);
9292
}
@@ -641,10 +641,6 @@ public static function provideSingleQuotedStringProvider(): array
641641
"$['\\u65e5\\u672c']",
642642
['Japan'],
643643
],
644-
[
645-
"$['quote\"here']",
646-
['with quote'],
647-
],
648644
[
649645
"$['M\\u00fcller']",
650646
[],
@@ -658,7 +654,7 @@ public static function provideSingleQuotedStringProvider(): array
658654
['with tab'],
659655
],
660656
[
661-
"$['quote\\\"here']",
657+
"$['quote\"here']",
662658
['with quote'],
663659
],
664660
[
@@ -725,29 +721,6 @@ public static function provideFilterWithUnicodeProvider(): array
725721
];
726722
}
727723

728-
/**
729-
* @dataProvider provideInvalidUnicodeSequenceProvider
730-
*/
731-
public function testInvalidUnicodeSequencesAreProcessedAsLiterals(string $jsonPath)
732-
{
733-
$this->assertIsArray(self::getUnicodeDocumentCrawler()->find($jsonPath), 'invalid unicode sequence should be treated as literal and not throw');
734-
}
735-
736-
public static function provideInvalidUnicodeSequenceProvider(): array
737-
{
738-
return [
739-
[
740-
'$["test\uZZZZ"]',
741-
],
742-
[
743-
'$["test\u123"]',
744-
],
745-
[
746-
'$["test\u"]',
747-
],
748-
];
749-
}
750-
751724
/**
752725
* @dataProvider provideComplexUnicodePath
753726
*/

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

Lines changed: 0 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -148,30 +148,6 @@ final class JsonPathComplianceTestSuiteTest extends TestCase
148148
'index selector, leading 0',
149149
'index selector, -0',
150150
'index selector, leading -0',
151-
'name selector, double quotes, escaped line feed',
152-
'name selector, double quotes, invalid escaped single quote',
153-
'name selector, double quotes, question mark escape',
154-
'name selector, double quotes, bell escape',
155-
'name selector, double quotes, vertical tab escape',
156-
'name selector, double quotes, 0 escape',
157-
'name selector, double quotes, x escape',
158-
'name selector, double quotes, n escape',
159-
'name selector, double quotes, unicode escape no hex',
160-
'name selector, double quotes, unicode escape too few hex',
161-
'name selector, double quotes, unicode escape upper u',
162-
'name selector, double quotes, unicode escape upper u long',
163-
'name selector, double quotes, unicode escape plus',
164-
'name selector, double quotes, unicode escape brackets',
165-
'name selector, double quotes, unicode escape brackets long',
166-
'name selector, double quotes, single high surrogate',
167-
'name selector, double quotes, single low surrogate',
168-
'name selector, double quotes, high high surrogate',
169-
'name selector, double quotes, low low surrogate',
170-
'name selector, double quotes, supplementary surrogate',
171-
'name selector, double quotes, surrogate incomplete low',
172-
'name selector, single quotes, escaped backspace',
173-
'name selector, single quotes, escaped line feed',
174-
'name selector, single quotes, invalid escaped double quote',
175151
'slice selector, excessively large from value with negative step',
176152
'slice selector, step, min exact - 1',
177153
'slice selector, step, max exact + 1',

0 commit comments

Comments
 (0)