diff --git a/build/psalm-baseline-security.xml b/build/psalm-baseline-security.xml
index 32939a14aec01..270b409bc6468 100644
--- a/build/psalm-baseline-security.xml
+++ b/build/psalm-baseline-security.xml
@@ -28,9 +28,7 @@
-
- cache]]>
-
+
diff --git a/lib/private/Config.php b/lib/private/Config.php
index 0e8d07955af06..a605a9201c8a8 100644
--- a/lib/private/Config.php
+++ b/lib/private/Config.php
@@ -18,6 +18,8 @@ class Config {
/** @var array Associative array ($key => $value) */
protected $cache = [];
+ /** @var array> */
+ protected array $cachePaths = [];
/** @var array */
protected $envCache = [];
/** @var string */
@@ -122,6 +124,12 @@ public function setValue($key, $value) {
*/
protected function set($key, $value) {
if (!isset($this->cache[$key]) || $this->cache[$key] !== $value) {
+ foreach ($this->cachePaths as $file => $keys) {
+ if ($file !== $this->configFilePath && in_array($key, $keys)) {
+ throw new HintException('The config key "' . $key . '" is already specified in "' . $file . '" and thus can not be overwritten.');
+ }
+ }
+
// Add change
$this->cache[$key] = $value;
return true;
@@ -152,6 +160,12 @@ public function deleteKey($key) {
*/
protected function delete($key) {
if (isset($this->cache[$key])) {
+ foreach ($this->cachePaths as $file => $keys) {
+ if ($file !== $this->configFilePath && in_array($key, $keys)) {
+ throw new HintException('The config key "' . $key . '" is already specified in "' . $file . '" and thus can not be overwritten.');
+ }
+ }
+
// Delete key from cache
unset($this->cache[$key]);
return true;
@@ -223,6 +237,7 @@ private function readData() {
}
if (isset($CONFIG) && is_array($CONFIG)) {
$this->cache = array_merge($this->cache, $CONFIG);
+ $this->cachePaths[$file] = array_keys($CONFIG);
}
}
@@ -253,10 +268,22 @@ private function writeData() {
throw new HintException(sprintf('Configuration was not read or initialized correctly, not overwriting %s', $this->configFilePath));
}
+ // Do not save any of the values that came from the extra config file into the main config file
+ $values = $this->cache;
+ foreach (array_keys($this->cachePaths) as $file) {
+ if ($file === $this->configFilePath) {
+ continue;
+ }
+
+ foreach ($this->cachePaths[$file] as $key) {
+ unset($values[$key]);
+ }
+ }
+
// Create a php file ...
$content = "cache, true);
+ $content .= var_export($values, true);
$content .= ";\n";
touch($this->configFilePath);
diff --git a/tests/lib/ConfigTest.php b/tests/lib/ConfigTest.php
index 3be066c68390e..30eb78779be6f 100644
--- a/tests/lib/ConfigTest.php
+++ b/tests/lib/ConfigTest.php
@@ -8,6 +8,7 @@
namespace Test;
use OC\Config;
+use OCP\HintException;
class ConfigTest extends TestCase {
public const TESTCONTENT = '"bar", "beers" => array("Appenzeller", "Guinness", "Kölsch"), "alcohol_free" => false);';
@@ -154,7 +155,7 @@ public function testDeleteKey(): void {
public function testConfigMerge(): void {
// Create additional config
- $additionalConfig = '"totallyOutdated");';
+ $additionalConfig = '"totallyOutdated","alcohol_free"=>true);';
$additionalConfigPath = $this->randomTmpDir . 'additionalConfig.testconfig.php';
file_put_contents($additionalConfigPath, $additionalConfig);
@@ -168,11 +169,32 @@ public function testConfigMerge(): void {
// Write a new value to the config
$config->setValue('CoolWebsites', ['demo.owncloud.org', 'owncloud.org', 'owncloud.com']);
$expected = " 'bar',\n 'beers' => \n array (\n 0 => 'Appenzeller',\n " .
- " 1 => 'Guinness',\n 2 => 'Kölsch',\n ),\n 'alcohol_free' => false,\n 'php53' => 'totallyOutdated',\n 'CoolWebsites' => \n array (\n " .
+ " 1 => 'Guinness',\n 2 => 'Kölsch',\n ),\n 'CoolWebsites' => \n array (\n " .
" 0 => 'demo.owncloud.org',\n 1 => 'owncloud.org',\n 2 => 'owncloud.com',\n ),\n);\n";
$this->assertEquals($expected, file_get_contents($this->configFile));
// Cleanup
unlink($additionalConfigPath);
}
+
+ public function testConfigAdditionalSetDelete(): void {
+ $additionalConfig = '"totallyOutdated");';
+ $additionalConfigPath = $this->randomTmpDir . 'additionalConfig.testconfig.php';
+ file_put_contents($additionalConfigPath, $additionalConfig);
+
+ $config = new Config($this->randomTmpDir, 'testconfig.php');
+
+ $this->assertSame('totallyOutdated', $config->getValue('php53', 'bogusValue'));
+ $this->assertEquals(self::TESTCONTENT, file_get_contents($this->configFile));
+
+ $this->expectException(HintException::class);
+
+ $this->expectExceptionMessage('The config key "php53" is already specified in "' . $additionalConfigPath . '" and thus can not be overwritten.');
+ $config->setValue('php53', 'actuallyNew');
+
+ $this->expectExceptionMessage('The config key "php53" is specified in "' . $additionalConfigPath . '" and thus can not be deleted.');
+ $config->deleteKey('php53');
+
+ unlink($additionalConfigPath);
+ }
}