From c7da7e55c96398b85ea13685d637b46cb72bd44a Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Sun, 22 Nov 2020 14:26:07 +0100 Subject: [PATCH] Fix various issues with regard to schema conformity when modifying json, fixes #9515 --- src/Composer/Config/JsonConfigSource.php | 28 +++++++++++++++++++++--- src/Composer/Json/JsonManipulator.php | 2 +- 2 files changed, 26 insertions(+), 4 deletions(-) diff --git a/src/Composer/Config/JsonConfigSource.php b/src/Composer/Config/JsonConfigSource.php index 5c0c04a06..e3d3729d8 100644 --- a/src/Composer/Config/JsonConfigSource.php +++ b/src/Composer/Config/JsonConfigSource.php @@ -14,6 +14,7 @@ namespace Composer\Config; use Composer\Json\JsonFile; use Composer\Json\JsonManipulator; +use Composer\Json\JsonValidationException; use Composer\Util\Silencer; /** @@ -251,14 +252,35 @@ class JsonConfigSource implements ConfigSourceInterface $this->arrayUnshiftRef($args, $config); call_user_func_array($fallback, $args); // avoid ending up with arrays for keys that should be objects - foreach (array('require', 'require-dev', 'conflict', 'provide', 'replace', 'suggest', 'config', 'autoload', 'autoload-dev') as $linkType) { - if (isset($config[$linkType]) && $config[$linkType] === array()) { - $config[$linkType] = new \stdClass; + foreach (array('require', 'require-dev', 'conflict', 'provide', 'replace', 'suggest', 'config', 'autoload', 'autoload-dev', 'scripts', 'scripts-descriptions', 'support', ) as $prop) { + if (isset($config[$prop]) && $config[$prop] === array()) { + $config[$prop] = new \stdClass; + } + } + foreach (array('psr-0', 'psr-4') as $prop) { + if (isset($config['autoload'][$prop]) && $config['autoload'][$prop] === array()) { + $config['autoload'][$prop] = new \stdClass; + } + if (isset($config['autoload-dev'][$prop]) && $config['autoload-dev'][$prop] === array()) { + $config['autoload-dev'][$prop] = new \stdClass; + } + } + foreach (array('platform', 'http-basic', 'bearer', 'gitlab-token', 'gitlab-oauth', 'github-oauth', 'preferred-install') as $prop) { + if (isset($config['config'][$prop]) && $config['config'][$prop] === array()) { + $config['config'][$prop] = new \stdClass; } } $this->file->write($config); } + try { + $this->file->validateSchema(JsonFile::LAX_SCHEMA); + } catch (JsonValidationException $e) { + // restore contents to the original state + file_put_contents($this->file->getPath(), $contents); + throw new \RuntimeException('Failed to update composer.json with a valid format, reverting to the original content. Please report an issue to us with details (command you run and a copy of your composer.json).', 0, $e); + } + if ($newFile) { Silencer::call('chmod', $this->file->getPath(), 0600); } diff --git a/src/Composer/Json/JsonManipulator.php b/src/Composer/Json/JsonManipulator.php index 249116cfb..d6b196e7d 100644 --- a/src/Composer/Json/JsonManipulator.php +++ b/src/Composer/Json/JsonManipulator.php @@ -492,7 +492,7 @@ class JsonManipulator return $this->removeMainKey($key); } - return false; + return true; } public function format($data, $depth = 0)