Skip to content

[JsonPath] Improve escape sequence validation in name selector #60802

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
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 9 additions & 11 deletions src/Symfony/Component/JsonPath/JsonPathUtils.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
namespace Symfony\Component\JsonPath;

use Symfony\Component\JsonPath\Exception\InvalidArgumentException;
use Symfony\Component\JsonPath\Exception\JsonCrawlerException;
use Symfony\Component\JsonPath\Tokenizer\JsonPathToken;
use Symfony\Component\JsonPath\Tokenizer\TokenType;
use Symfony\Component\JsonStreamer\Read\Splitter;
Expand Down Expand Up @@ -86,6 +87,9 @@ public static function findSmallestDeserializableStringAndPath(array $tokens, mi
];
}

/**
* @throws JsonCrawlerException When an invalid Unicode escape sequence occurs
*/
public static function unescapeString(string $str, string $quoteChar): string
{
if ('"' === $quoteChar) {
Expand All @@ -104,17 +108,16 @@ public static function unescapeString(string $str, string $quoteChar): string
while (null !== $char = $str[++$i] ?? null) {
if ('\\' === $char && isset($str[$i + 1])) {
$result .= match ($str[$i + 1]) {
'"' => '"',
"'" => "'",
'\\' => '\\',
'/' => '/',
'b' => "\b",
'b' => "\x08",
'f' => "\f",
'n' => "\n",
'r' => "\r",
't' => "\t",
'u' => self::unescapeUnicodeSequence($str, $i),
default => $char.$str[$i + 1], // keep the backslash
$quoteChar => $quoteChar,
default => throw new JsonCrawlerException('', \sprintf('Invalid escape sequence "\\%s" in %s-quoted string', $str[$i + 1], "'" === $quoteChar ? 'single' : 'double')),
};

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

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

$hex = substr($str, $i + 2, 4);
if (!ctype_xdigit($hex)) {
// invalid hex, treat as literal
return $str[$i];
}

$codepoint = hexdec($hex);
// looks like a valid Unicode codepoint, string length is sufficient and it starts with \u
Expand Down
31 changes: 2 additions & 29 deletions src/Symfony/Component/JsonPath/Tests/JsonCrawlerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ public function testEscapedDoubleQuotesInFieldName()
{"a": {"b\\"c": 42}}
JSON);

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

$this->assertSame(42, $result[0]);
}
Expand Down Expand Up @@ -641,10 +641,6 @@ public static function provideSingleQuotedStringProvider(): array
"$['\\u65e5\\u672c']",
['Japan'],
],
[
"$['quote\"here']",
['with quote'],
],
[
"$['M\\u00fcller']",
[],
Expand All @@ -658,7 +654,7 @@ public static function provideSingleQuotedStringProvider(): array
['with tab'],
],
[
"$['quote\\\"here']",
"$['quote\"here']",
['with quote'],
],
[
Expand Down Expand Up @@ -725,29 +721,6 @@ public static function provideFilterWithUnicodeProvider(): array
];
}

/**
* @dataProvider provideInvalidUnicodeSequenceProvider
*/
public function testInvalidUnicodeSequencesAreProcessedAsLiterals(string $jsonPath)
{
$this->assertIsArray(self::getUnicodeDocumentCrawler()->find($jsonPath), 'invalid unicode sequence should be treated as literal and not throw');
}

public static function provideInvalidUnicodeSequenceProvider(): array
{
return [
[
'$["test\uZZZZ"]',
],
[
'$["test\u123"]',
],
[
'$["test\u"]',
],
];
}

/**
* @dataProvider provideComplexUnicodePath
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -148,30 +148,6 @@ final class JsonPathComplianceTestSuiteTest extends TestCase
'index selector, leading 0',
'index selector, -0',
'index selector, leading -0',
'name selector, double quotes, escaped line feed',
'name selector, double quotes, invalid escaped single quote',
'name selector, double quotes, question mark escape',
'name selector, double quotes, bell escape',
'name selector, double quotes, vertical tab escape',
'name selector, double quotes, 0 escape',
'name selector, double quotes, x escape',
'name selector, double quotes, n escape',
'name selector, double quotes, unicode escape no hex',
'name selector, double quotes, unicode escape too few hex',
'name selector, double quotes, unicode escape upper u',
'name selector, double quotes, unicode escape upper u long',
'name selector, double quotes, unicode escape plus',
'name selector, double quotes, unicode escape brackets',
'name selector, double quotes, unicode escape brackets long',
'name selector, double quotes, single high surrogate',
'name selector, double quotes, single low surrogate',
'name selector, double quotes, high high surrogate',
'name selector, double quotes, low low surrogate',
'name selector, double quotes, supplementary surrogate',
'name selector, double quotes, surrogate incomplete low',
'name selector, single quotes, escaped backspace',
'name selector, single quotes, escaped line feed',
'name selector, single quotes, invalid escaped double quote',
'slice selector, excessively large from value with negative step',
'slice selector, step, min exact - 1',
'slice selector, step, max exact + 1',
Expand Down
Loading
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy