parent
1e6ceea0f9
commit
5a22a4f1f3
|
@ -69,6 +69,13 @@ class JsonFormatter
|
||||||
$l = strlen($match[1]);
|
$l = strlen($match[1]);
|
||||||
|
|
||||||
if ($l % 2) {
|
if ($l % 2) {
|
||||||
|
$code = hexdec($match[2]);
|
||||||
|
// 0xD800..0xDFFF denotes UTF-16 surrogate pair which won't be unescaped
|
||||||
|
// see https://github.com/composer/composer/issues/7510
|
||||||
|
if (0xD800 <= $code && 0xDFFF >= $code) {
|
||||||
|
return $match[0];
|
||||||
|
}
|
||||||
|
|
||||||
return str_repeat('\\', $l - 1) . mb_convert_encoding(
|
return str_repeat('\\', $l - 1) . mb_convert_encoding(
|
||||||
pack('H*', $match[2]),
|
pack('H*', $match[2]),
|
||||||
'UTF-8',
|
'UTF-8',
|
||||||
|
|
|
@ -33,6 +33,20 @@ class JsonFormatterTest extends TestCase
|
||||||
$this->assertEquals($expected, $this->getCharacterCodes($encodedData));
|
$this->assertEquals($expected, $this->getCharacterCodes($encodedData));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Surrogate pairs are intentionally skipped and not unescaped
|
||||||
|
* https://github.com/composer/composer/issues/7510
|
||||||
|
*/
|
||||||
|
public function testUtf16SurrogatePair()
|
||||||
|
{
|
||||||
|
if (!extension_loaded('mbstring')) {
|
||||||
|
$this->markTestSkipped('Test requires the mbstring extension');
|
||||||
|
}
|
||||||
|
|
||||||
|
$escaped = '"\ud83d\ude00"';
|
||||||
|
$this->assertEquals($escaped, JsonFormatter::format($escaped, true, true));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convert string to character codes split by a plus sign
|
* Convert string to character codes split by a plus sign
|
||||||
* @param string $string
|
* @param string $string
|
||||||
|
|
Loading…
Reference in New Issue