From f0de4f2da3ebf9058306669a08e5e95fbea837fb Mon Sep 17 00:00:00 2001 From: Andriy Redko Date: Tue, 13 Feb 2024 17:05:33 -0500 Subject: [PATCH] Add a system property to configure YamlParser codepoint limits (#12301) Signed-off-by: Andriy Redko (cherry picked from commit bff8eb7e3ef011a0575f064e51716d76f3447c80) --- CHANGELOG.md | 1 + .../org/opensearch/common/xcontent/XContentContraints.java | 3 +++ .../org/opensearch/common/xcontent/yaml/YamlXContent.java | 7 ++++++- .../opensearch/common/xcontent/XContentParserTests.java | 4 ++-- 4 files changed, 12 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1a8ddee0bd403..97f2be0b4f65d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), ### Removed ### Fixed +- Add a system property to configure YamlParser codepoint limits ([#12298](https://github.com/opensearch-project/OpenSearch/pull/12298)) ### Security diff --git a/libs/x-content/src/main/java/org/opensearch/common/xcontent/XContentContraints.java b/libs/x-content/src/main/java/org/opensearch/common/xcontent/XContentContraints.java index 0b80bec8577d0..0f0a6060064a6 100644 --- a/libs/x-content/src/main/java/org/opensearch/common/xcontent/XContentContraints.java +++ b/libs/x-content/src/main/java/org/opensearch/common/xcontent/XContentContraints.java @@ -19,6 +19,7 @@ */ @InternalApi public interface XContentContraints { + final String DEFAULT_CODEPOINT_LIMIT_PROPERTY = "opensearch.xcontent.codepoint.max"; final String DEFAULT_MAX_STRING_LEN_PROPERTY = "opensearch.xcontent.string.length.max"; final String DEFAULT_MAX_NAME_LEN_PROPERTY = "opensearch.xcontent.name.length.max"; final String DEFAULT_MAX_DEPTH_PROPERTY = "opensearch.xcontent.depth.max"; @@ -34,4 +35,6 @@ public interface XContentContraints { final int DEFAULT_MAX_DEPTH = Integer.parseInt( System.getProperty(DEFAULT_MAX_DEPTH_PROPERTY, Integer.toString(Integer.MAX_VALUE) /* no limit */ ) ); + + final int DEFAULT_CODEPOINT_LIMIT = Integer.parseInt(System.getProperty(DEFAULT_CODEPOINT_LIMIT_PROPERTY, "52428800" /* ~50 Mb */)); } diff --git a/libs/x-content/src/main/java/org/opensearch/common/xcontent/yaml/YamlXContent.java b/libs/x-content/src/main/java/org/opensearch/common/xcontent/yaml/YamlXContent.java index 661f22d389036..6a9e5953d9b56 100644 --- a/libs/x-content/src/main/java/org/opensearch/common/xcontent/yaml/YamlXContent.java +++ b/libs/x-content/src/main/java/org/opensearch/common/xcontent/yaml/YamlXContent.java @@ -39,6 +39,7 @@ import com.fasterxml.jackson.core.StreamWriteConstraints; import com.fasterxml.jackson.core.StreamWriteFeature; import com.fasterxml.jackson.dataformat.yaml.YAMLFactory; +import com.fasterxml.jackson.dataformat.yaml.YAMLFactoryBuilder; import org.opensearch.common.xcontent.XContentContraints; import org.opensearch.common.xcontent.XContentType; @@ -56,6 +57,8 @@ import java.io.Reader; import java.util.Set; +import org.yaml.snakeyaml.LoaderOptions; + /** * A YAML based content implementation using Jackson. */ @@ -70,7 +73,9 @@ public static XContentBuilder contentBuilder() throws IOException { public static final YamlXContent yamlXContent; static { - yamlFactory = new YAMLFactory(); + final LoaderOptions loaderOptions = new LoaderOptions(); + loaderOptions.setCodePointLimit(DEFAULT_CODEPOINT_LIMIT); + yamlFactory = new YAMLFactoryBuilder(new YAMLFactory()).loaderOptions(loaderOptions).build(); yamlFactory.configure(JsonParser.Feature.STRICT_DUPLICATE_DETECTION, true); yamlFactory.setStreamWriteConstraints(StreamWriteConstraints.builder().maxNestingDepth(DEFAULT_MAX_DEPTH).build()); yamlFactory.setStreamReadConstraints( diff --git a/libs/x-content/src/test/java/org/opensearch/common/xcontent/XContentParserTests.java b/libs/x-content/src/test/java/org/opensearch/common/xcontent/XContentParserTests.java index 5ca8b94c9f807..45f39086dc3b1 100644 --- a/libs/x-content/src/test/java/org/opensearch/common/xcontent/XContentParserTests.java +++ b/libs/x-content/src/test/java/org/opensearch/common/xcontent/XContentParserTests.java @@ -79,7 +79,7 @@ public class XContentParserTests extends OpenSearchTestCase { () -> randomAlphaOfLengthBetween(1, SmileXContent.DEFAULT_MAX_STRING_LEN / 10), /* limit to ~200Mb */ /* YAML parser limitation */ XContentType.YAML, - () -> randomAlphaOfLengthBetween(1, 3140000) + () -> randomRealisticUnicodeOfCodepointLengthBetween(1, YamlXContent.DEFAULT_CODEPOINT_LIMIT) ); private static final Map> FIELD_NAME_GENERATORS = Map.of( @@ -106,7 +106,7 @@ public class XContentParserTests extends OpenSearchTestCase { public void testStringOffLimit() throws IOException { final String field = randomAlphaOfLengthBetween(1, 5); - final String value = randomRealisticUnicodeOfCodepointLength(3145730); + final String value = randomRealisticUnicodeOfCodepointLength(YamlXContent.DEFAULT_CODEPOINT_LIMIT + 1); try (XContentBuilder builder = XContentBuilder.builder(XContentType.YAML.xContent())) { builder.startObject();