This is an automated email from the ASF dual-hosted git repository. oheger pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/commons-configuration.git
The following commit(s) were added to refs/heads/master by this push: new add7375 Prevent object creation when loading YAML files. add7375 is described below commit add7375cf37fd316d4838c6c56b054fc293b4641 Author: oheger <oliver.he...@oliver-heger.de> AuthorDate: Wed Mar 4 21:33:22 2020 +0100 Prevent object creation when loading YAML files. When creating a new Yaml instance from SnakeYaml to read in a configuration file the instance is now configured that no objects are created automatically. --- .../commons/configuration2/YAMLConfiguration.java | 41 +++++++++++++++-- .../configuration2/TestYAMLConfiguration.java | 53 ++++++++++++++++++++-- 2 files changed, 87 insertions(+), 7 deletions(-) diff --git a/src/main/java/org/apache/commons/configuration2/YAMLConfiguration.java b/src/main/java/org/apache/commons/configuration2/YAMLConfiguration.java index 1593d12..2b15d66 100644 --- a/src/main/java/org/apache/commons/configuration2/YAMLConfiguration.java +++ b/src/main/java/org/apache/commons/configuration2/YAMLConfiguration.java @@ -18,11 +18,14 @@ package org.apache.commons.configuration2; import org.apache.commons.configuration2.ex.ConfigurationException; +import org.apache.commons.configuration2.ex.ConfigurationRuntimeException; import org.apache.commons.configuration2.io.InputStreamSupport; import org.apache.commons.configuration2.tree.ImmutableNode; import org.yaml.snakeyaml.DumperOptions; import org.yaml.snakeyaml.LoaderOptions; import org.yaml.snakeyaml.Yaml; +import org.yaml.snakeyaml.constructor.Constructor; +import org.yaml.snakeyaml.representer.Representer; import java.io.IOException; import java.io.InputStream; @@ -65,7 +68,7 @@ public class YAMLConfiguration extends AbstractYAMLBasedConfiguration { try { - final Yaml yaml = new Yaml(); + final Yaml yaml = createYamlForReading(new LoaderOptions()); final Map<String, Object> map = (Map) yaml.load(in); load(map); } @@ -80,7 +83,7 @@ public class YAMLConfiguration extends AbstractYAMLBasedConfiguration { try { - final Yaml yaml = new Yaml(options); + final Yaml yaml = createYamlForReading(options); final Map<String, Object> map = (Map) yaml.load(in); load(map); } @@ -117,7 +120,7 @@ public class YAMLConfiguration extends AbstractYAMLBasedConfiguration { try { - final Yaml yaml = new Yaml(); + final Yaml yaml = createYamlForReading(new LoaderOptions()); final Map<String, Object> map = (Map) yaml.load(in); load(map); } @@ -132,7 +135,7 @@ public class YAMLConfiguration extends AbstractYAMLBasedConfiguration { try { - final Yaml yaml = new Yaml(options); + final Yaml yaml = createYamlForReading(options); final Map<String, Object> map = (Map) yaml.load(in); load(map); } @@ -142,4 +145,34 @@ public class YAMLConfiguration extends AbstractYAMLBasedConfiguration } } + /** + * Creates a {@code Yaml} object for reading a Yaml file. The object is + * configured with some default settings. + * + * @param options options for loading the file + * @return the {@code Yaml} instance for loading a file + */ + private static Yaml createYamlForReading(LoaderOptions options) + { + return new Yaml(createClassLoadingDisablingConstructor(), new Representer(), new DumperOptions(), options); + } + + /** + * Returns a {@code Constructor} object for the YAML parser that prevents + * all classes from being loaded. This effectively disables the dynamic + * creation of Java objects that are declared in YAML files to be loaded. + * + * @return the {@code Constructor} preventing object creation + */ + private static Constructor createClassLoadingDisablingConstructor() + { + return new Constructor() + { + @Override + protected Class<?> getClassForName(String name) + { + throw new ConfigurationRuntimeException("Class loading is disabled."); + } + }; + } } diff --git a/src/test/java/org/apache/commons/configuration2/TestYAMLConfiguration.java b/src/test/java/org/apache/commons/configuration2/TestYAMLConfiguration.java index dbdaea0..0945a30 100644 --- a/src/test/java/org/apache/commons/configuration2/TestYAMLConfiguration.java +++ b/src/test/java/org/apache/commons/configuration2/TestYAMLConfiguration.java @@ -17,26 +17,37 @@ package org.apache.commons.configuration2; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; - +import java.io.ByteArrayInputStream; +import java.io.File; import java.io.FileReader; import java.io.IOException; +import java.io.StringReader; import java.io.StringWriter; +import java.nio.charset.StandardCharsets; import java.util.Arrays; import java.util.List; import java.util.Map; import org.apache.commons.configuration2.ex.ConfigurationException; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.TemporaryFolder; import org.yaml.snakeyaml.Yaml; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + /** * Unit test for {@link YAMLConfiguration} */ public class TestYAMLConfiguration { + @Rule + public TemporaryFolder temporaryFolder = new TemporaryFolder(); + /** The files that we test with. */ private final String testYaml = ConfigurationAssert.getTestFile("test.yaml").getAbsolutePath(); @@ -134,4 +145,40 @@ public class TestYAMLConfiguration yamlConfiguration = new YAMLConfiguration(c); assertEquals("bar", yamlConfiguration.getString("foo")); } + + @Test + public void testObjectCreationFromReader() + { + final File createdFile = new File(temporaryFolder.getRoot(), "data.txt"); + final String yaml = "!!java.io.FileOutputStream [" + createdFile.getAbsolutePath() + "]"; + + try + { + yamlConfiguration.read(new StringReader(yaml)); + fail("Loading configuration did not cause an exception!"); + } + catch (ConfigurationException e) + { + //expected + } + assertFalse("Java object was created", createdFile.exists()); + } + + @Test + public void testObjectCreationFromStream() + { + final File createdFile = new File(temporaryFolder.getRoot(), "data.txt"); + final String yaml = "!!java.io.FileOutputStream [" + createdFile.getAbsolutePath() + "]"; + + try + { + yamlConfiguration.read(new ByteArrayInputStream(yaml.getBytes(StandardCharsets.UTF_8))); + fail("Loading configuration did not cause an exception!"); + } + catch (ConfigurationException e) + { + //expected + } + assertFalse("Java object was created", createdFile.exists()); + } }