[DependencyInjection][Translator] Silent deprecation triggered by libxml_disable_entity_loader

This commit is contained in:
Jérémy Derussé 2020-11-12 21:59:34 +01:00 committed by Fabien Potencier
parent cdfa9c2d8b
commit 114b7a543a
5 changed files with 112 additions and 13 deletions

View File

@ -634,14 +634,13 @@ $imports
EOF
;
if (\LIBXML_VERSION < 20900) {
if ($this->shouldEnableEntityLoader()) {
$disableEntities = libxml_disable_entity_loader(false);
$valid = @$dom->schemaValidateSource($source);
libxml_disable_entity_loader($disableEntities);
} else {
$valid = @$dom->schemaValidateSource($source);
}
foreach ($tmpfiles as $tmpfile) {
@unlink($tmpfile);
}
@ -649,6 +648,36 @@ EOF
return $valid;
}
private function shouldEnableEntityLoader(): bool
{
// Version prior to 8.0 can be enabled without deprecation
if (\PHP_VERSION_ID < 80000) {
return true;
}
static $dom, $schema;
if (null === $dom) {
$dom = new \DOMDocument();
$dom->loadXML('<?xml version="1.0"?><test/>');
$tmpfile = tempnam(sys_get_temp_dir(), 'symfony');
register_shutdown_function(static function () use ($tmpfile) {
@unlink($tmpfile);
});
$schema = '<?xml version="1.0" encoding="utf-8"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:include schemaLocation="file:///'.str_replace('\\', '/', $tmpfile).'" />
</xsd:schema>';
file_put_contents($tmpfile, '<?xml version="1.0" encoding="utf-8"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:element name="test" type="testType" />
<xsd:complexType name="testType"/>
</xsd:schema>');
}
return !@$dom->schemaValidateSource($schema);
}
private function validateAlias(\DOMElement $alias, string $file)
{
foreach ($alias->attributes as $name => $node) {

View File

@ -29,6 +29,21 @@ class TranslationFilesTest extends TestCase
$this->assertCount(0, $errors, sprintf('"%s" is invalid:%s', $filePath, \PHP_EOL.implode(\PHP_EOL, array_column($errors, 'message'))));
}
/**
* @dataProvider provideTranslationFiles
* @group Legacy
*/
public function testTranslationFileIsValidWithoutEntityLoader($filePath)
{
$document = new \DOMDocument();
$document->loadXML(file_get_contents($filePath));
libxml_disable_entity_loader(true);
$errors = XliffUtils::validateSchema($document);
$this->assertCount(0, $errors, sprintf('"%s" is invalid:%s', $filePath, \PHP_EOL.implode(\PHP_EOL, array_column($errors, 'message'))));
}
public function provideTranslationFiles()
{
return array_map(

View File

@ -29,6 +29,20 @@ class TranslationFilesTest extends TestCase
$this->assertCount(0, $errors, sprintf('"%s" is invalid:%s', $filePath, \PHP_EOL.implode(\PHP_EOL, array_column($errors, 'message'))));
}
/**
* @dataProvider provideTranslationFiles
*/
public function testTranslationFileIsValidWithoutEntityLoader($filePath)
{
$document = new \DOMDocument();
$document->loadXML(file_get_contents($filePath));
libxml_disable_entity_loader(true);
$errors = XliffUtils::validateSchema($document);
$this->assertCount(0, $errors, sprintf('"%s" is invalid:%s', $filePath, \PHP_EOL.implode(\PHP_EOL, array_column($errors, 'message'))));
}
public function provideTranslationFiles()
{
return array_map(

View File

@ -61,21 +61,18 @@ class XliffUtils
{
$xliffVersion = static::getVersionNumber($dom);
$internalErrors = libxml_use_internal_errors(true);
if (\LIBXML_VERSION < 20900) {
if ($shouldEnable = self::shouldEnableEntityLoader()) {
$disableEntities = libxml_disable_entity_loader(false);
}
$isValid = @$dom->schemaValidateSource(self::getSchema($xliffVersion));
if (!$isValid) {
if (\LIBXML_VERSION < 20900) {
try {
$isValid = @$dom->schemaValidateSource(self::getSchema($xliffVersion));
if (!$isValid) {
return self::getXmlErrors($internalErrors);
}
} finally {
if ($shouldEnable) {
libxml_disable_entity_loader($disableEntities);
}
return self::getXmlErrors($internalErrors);
}
if (\LIBXML_VERSION < 20900) {
libxml_disable_entity_loader($disableEntities);
}
$dom->normalizeDocument();
@ -86,6 +83,36 @@ class XliffUtils
return [];
}
private static function shouldEnableEntityLoader(): bool
{
// Version prior to 8.0 can be enabled without deprecation
if (\PHP_VERSION_ID < 80000) {
return true;
}
static $dom, $schema;
if (null === $dom) {
$dom = new \DOMDocument();
$dom->loadXML('<?xml version="1.0"?><test/>');
$tmpfile = tempnam(sys_get_temp_dir(), 'symfony');
register_shutdown_function(static function () use ($tmpfile) {
@unlink($tmpfile);
});
$schema = '<?xml version="1.0" encoding="utf-8"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:include schemaLocation="file:///'.str_replace('\\', '/', $tmpfile).'" />
</xsd:schema>';
file_put_contents($tmpfile, '<?xml version="1.0" encoding="utf-8"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:element name="test" type="testType" />
<xsd:complexType name="testType"/>
</xsd:schema>');
}
return !@$dom->schemaValidateSource($schema);
}
public static function getErrorsAsString(array $xmlErrors): string
{
$errorsAsString = '';

View File

@ -29,6 +29,20 @@ class TranslationFilesTest extends TestCase
$this->assertCount(0, $errors, sprintf('"%s" is invalid:%s', $filePath, \PHP_EOL.implode(\PHP_EOL, array_column($errors, 'message'))));
}
/**
* @dataProvider provideTranslationFiles
*/
public function testTranslationFileIsValidWithoutEntityLoader($filePath)
{
$document = new \DOMDocument();
$document->loadXML(file_get_contents($filePath));
libxml_disable_entity_loader(true);
$errors = XliffUtils::validateSchema($document);
$this->assertCount(0, $errors, sprintf('"%s" is invalid:%s', $filePath, \PHP_EOL.implode(\PHP_EOL, array_column($errors, 'message'))));
}
public function provideTranslationFiles()
{
return array_map(