This is an automated email from the ASF dual-hosted git repository. jsedding pushed a commit to branch jsedding/SLING-12366-read-inputstream-from-closed-session in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-xss.git
commit cf0cc5f057121d8d3ff5eb6fec761ff0e0b8bcf2 Author: Julian Sedding <jsedd...@apache.org> AuthorDate: Tue Jul 2 16:34:42 2024 +0200 SLING-12368 - regression: rule for "ol" tag fails on java 9+ after SLING-12276 - add failing unit test - fix some minor NullPointerExceptions uncovered by the test --- .../sling/xss/impl/AntiSamyPolicyAdapter.java | 9 ++-- .../apache/sling/xss/impl/xml/AntiSamyRules.java | 7 +-- .../org/apache/sling/xss/impl/xml/PolicyTest.java | 57 +++++++++++++++++++++- ...configWithoutDifferentCaseDuplicateLiterals.xml | 43 ++++++++++++++++ 4 files changed, 107 insertions(+), 9 deletions(-) diff --git a/src/main/java/org/apache/sling/xss/impl/AntiSamyPolicyAdapter.java b/src/main/java/org/apache/sling/xss/impl/AntiSamyPolicyAdapter.java index 5a682a3..cc0a381 100644 --- a/src/main/java/org/apache/sling/xss/impl/AntiSamyPolicyAdapter.java +++ b/src/main/java/org/apache/sling/xss/impl/AntiSamyPolicyAdapter.java @@ -23,6 +23,7 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Objects; import java.util.function.Predicate; import java.util.regex.Pattern; @@ -172,7 +173,7 @@ public class AntiSamyPolicyAdapter { Map<String, Attribute> dynamicAttributes = new HashMap<>(); // checks if the dynamic attributes are allowed - if (policy.getDirectives().get(ALLOW_DYNAMIC_ATTRIBUTES).equals("true")) { + if (Objects.equals(policy.getDirectives().get(ALLOW_DYNAMIC_ATTRIBUTES), "true")) { dynamicAttributes.putAll(policy.getDynamicAttributes()); for (Attribute attribute : dynamicAttributes.values()) { if (attribute.getOnInvalid().equals(REMOVE_TAG_ON_INVALID_ACTION)) { @@ -261,10 +262,10 @@ public class AntiSamyPolicyAdapter { Field f = Unsafe.class.getDeclaredField("theUnsafe"); f.setAccessible(true); Unsafe unsafe = (Unsafe) f.get(null); - + // required to be able to get the static field base unsafe.ensureClassInitialized(HtmlPolicyBuilder.class); - + Object fieldBase = unsafe.staticFieldBase(guards); long fieldOffset = unsafe.staticFieldOffset(guards); unsafe.putObject(fieldBase, fieldOffset, new HashMap<>()); @@ -273,4 +274,4 @@ public class AntiSamyPolicyAdapter { throw new IllegalStateException(e); } } -} \ No newline at end of file +} diff --git a/src/main/java/org/apache/sling/xss/impl/xml/AntiSamyRules.java b/src/main/java/org/apache/sling/xss/impl/xml/AntiSamyRules.java index 3c2c90e..d0af4ad 100644 --- a/src/main/java/org/apache/sling/xss/impl/xml/AntiSamyRules.java +++ b/src/main/java/org/apache/sling/xss/impl/xml/AntiSamyRules.java @@ -22,6 +22,7 @@ import java.util.Collections; import java.util.List; import java.util.Locale; import java.util.Map; +import java.util.Optional; import java.util.regex.Pattern; import java.util.stream.Collectors; @@ -77,11 +78,11 @@ public class AntiSamyRules { } public DynamicTagAttributes getDynamicTagAttribute() { - return dynamicTagAttribute; + return Optional.ofNullable(dynamicTagAttribute).orElseGet(DynamicTagAttributes::new); } public GlobalTagAttributes getGlobalTagAttributes() { - return globalTagAttributes; + return Optional.ofNullable(globalTagAttributes).orElseGet(GlobalTagAttributes::new); } public String getNoNamespaceSchemaLocation() { @@ -125,7 +126,7 @@ public class AntiSamyRules { return regexpList.stream() .collect(Collectors.toMap(Regexp::getName, Regexp::getPattern)); } - + /** * Attribute, Property and Tag names use the English locale, which may differ from the original config */ diff --git a/src/test/java/org/apache/sling/xss/impl/xml/PolicyTest.java b/src/test/java/org/apache/sling/xss/impl/xml/PolicyTest.java index a512fa1..799a650 100644 --- a/src/test/java/org/apache/sling/xss/impl/xml/PolicyTest.java +++ b/src/test/java/org/apache/sling/xss/impl/xml/PolicyTest.java @@ -22,19 +22,34 @@ import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertTrue; import java.io.InputStream; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import java.net.URISyntaxException; +import java.net.URL; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; import java.util.List; import java.util.Map; import java.util.regex.Pattern; +import org.apache.sling.xss.impl.HtmlSanitizer; import org.apache.sling.xss.impl.InvalidConfigException; import org.apache.sling.xss.impl.xml.AntiSamyPolicy.CssPolicy; import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.converter.ArgumentConversionException; +import org.junit.jupiter.params.converter.ConvertWith; +import org.junit.jupiter.params.converter.TypedArgumentConverter; +import org.junit.jupiter.params.provider.ValueSource; class PolicyTest { @Test - void loadDefaultPolicy() throws Exception, InvalidConfigException { - try(InputStream input = AntiSamyPolicy.class.getClassLoader().getResourceAsStream("SLING-INF/content/config.xml")) { + void loadDefaultPolicy() throws Exception { + try (InputStream input = AntiSamyPolicy.class.getClassLoader().getResourceAsStream("SLING-INF/content/config.xml")) { AntiSamyPolicy policy = new AntiSamyPolicy(input); Map<String, Pattern> regexp = policy.getCommonRegularExpressions(); List<String> empty = policy.getAllowedEmptyTags(); @@ -67,4 +82,42 @@ class PolicyTest { assertFalse(cssPolicy.isValidElementName("base|link")); } } + + @ParameterizedTest + @ValueSource(strings = { + "configWithoutDifferentCaseDuplicateLiterals.xml", + "configWithoutHref.xml", + "configWithAdditionalGlobalAndDynamicConditions.xml" + }) + void loadPolicyFile(@Resource Path configFile) throws Exception { + try (InputStream input = Files.newInputStream(configFile)) { + AntiSamyPolicy policy = new AntiSamyPolicy(input); + assertNotNull(policy); + HtmlSanitizer htmlSanitizer = new HtmlSanitizer(policy); + assertNotNull(htmlSanitizer); + } + } + + @Target({ElementType.PARAMETER}) + @Retention(RetentionPolicy.RUNTIME) + @ConvertWith(LoadResource.class) + @interface Resource {} + + private static class LoadResource extends TypedArgumentConverter<String, Path> { + + LoadResource() { + super(String.class, Path.class); + } + + @Override + protected Path convert(String relPath) throws ArgumentConversionException { + URL url = LoadResource.class.getClassLoader().getResource(relPath); + assertNotNull(url, "resource not found: " + relPath); + try { + return Paths.get(url.toURI()); + } catch (URISyntaxException e) { + throw new RuntimeException(e); + } + } + } } diff --git a/src/test/resources/configWithoutDifferentCaseDuplicateLiterals.xml b/src/test/resources/configWithoutDifferentCaseDuplicateLiterals.xml new file mode 100644 index 0000000..11ae5cf --- /dev/null +++ b/src/test/resources/configWithoutDifferentCaseDuplicateLiterals.xml @@ -0,0 +1,43 @@ +<?xml version="1.0" encoding="ISO-8859-1" ?> +<!--~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + ~ Licensed to the Apache Software Foundation (ASF) under one or + ~ more bundlesutor license agreements. See the NOTICE file + ~ distributed with this work for additional information regarding + ~ copyright ownership. The ASF licenses this file to you under the + ~ Apache License, Version 2.0 (the "License"); you may not use + ~ this file except in compliance with the License. You may obtain + ~ a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 Unless required by + ~ applicable law or agreed to in writing, software distributed + ~ under the License is distributed on an "AS IS" BASIS, WITHOUT + ~ WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions + ~ and limitations under the License. + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~--> +<!-- +W3C rules retrieved from: +http://www.w3.org/TR/html401/struct/global.html +--> +<anti-samy-rules xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="antisamy.xsd"> + + <tag-rules> + <tag name="ol" action="validate"> + <attribute name="start"> + <regexp-list> + <regexp value="[0-9]+"/> + </regexp-list> + </attribute> + <attribute name="type"> + <literal-list> + <literal value="a"/> + <literal value="A"/> + <literal value="i"/> + <literal value="I"/> + <literal value="1"/> + </literal-list> + </attribute> + </tag> + </tag-rules> + +</anti-samy-rules>