This is an automated email from the ASF dual-hosted git repository. joerghoh pushed a commit to branch SLING-13380 in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-api.git
commit d40296d3c778c7403dcdf34e41340176a29ed8f5 Author: Joerg Hoh <[email protected]> AuthorDate: Thu Oct 8 09:44:00 2026 +0200 SLING-13380 document existing (incorrect) behavior of Path.matches() and PathSet.matches() --- src/main/java/org/apache/sling/api/resource/path/Path.java | 14 ++++++++++++-- .../java/org/apache/sling/api/resource/path/PathSet.java | 8 ++++++++ .../org/apache/sling/api/resource/path/PathSetTest.java | 10 ++++++++++ .../java/org/apache/sling/api/resource/path/PathTest.java | 10 ++++++++++ 4 files changed, 40 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/apache/sling/api/resource/path/Path.java b/src/main/java/org/apache/sling/api/resource/path/Path.java index 77326aa..bccd814 100644 --- a/src/main/java/org/apache/sling/api/resource/path/Path.java +++ b/src/main/java/org/apache/sling/api/resource/path/Path.java @@ -102,8 +102,18 @@ public class Path implements Comparable<Path> { * provided path matches the pattern. If this path object holds a pattern * and a pattern is provided as the argument, it returns only {@code true} * if the pattern is the same. - * If the provided argument is not an absolute path (e.g. if it is a relative - * path or a pattern), this method returns {@code false}. + * If the provided argument is not an absolute path or an absolute glob + * pattern, this method throws {@code IllegalArgumentException}. + * + * <p><strong>Warning:</strong> A glob pattern supplied as {@code otherPath} + * can produce an incorrect result if this method is used as a containment + * check. For example, {@code new Path("/apps").matches("glob:/**")} returns + * {@code true}, although {@code glob:/**} is not a concrete path inside + * {@code /apps} and also matches paths outside that subtree. Pattern + * arguments establish overlap, not containment of all matching paths. + * For concrete-path containment or authorization checks, callers must + * ensure that {@code otherPath} is a concrete absolute path, not a glob + * pattern. See <a href="https://issues.apache.org/jira/browse/SLING-13380">SLING-13380</a>.</p> * * @param otherPath Absolute path to check. * @return {@code true} If other path is within the sub tree of this path diff --git a/src/main/java/org/apache/sling/api/resource/path/PathSet.java b/src/main/java/org/apache/sling/api/resource/path/PathSet.java index 3bb6324..fb9fd3a 100644 --- a/src/main/java/org/apache/sling/api/resource/path/PathSet.java +++ b/src/main/java/org/apache/sling/api/resource/path/PathSet.java @@ -125,6 +125,14 @@ public class PathSet implements Iterable<Path> { /** * Check whether the provided path is in the sub tree of any * of the paths in this set. + * + * <p><strong>Warning:</strong> Glob patterns supplied as {@code otherPath} + * can produce incorrect containment results. See {@link Path#matches(String)} + * for an example and the distinction between pattern overlap and containment. + * For concrete-path containment or authorization checks, callers must + * ensure that {@code otherPath} is a concrete absolute path, not a glob + * pattern. See <a href="https://issues.apache.org/jira/browse/SLING-13380">SLING-13380</a>.</p> + * * @param otherPath The path to match * @return The path which matches the provided path, {@code null} otherwise. * @see Path#matches(String) diff --git a/src/test/java/org/apache/sling/api/resource/path/PathSetTest.java b/src/test/java/org/apache/sling/api/resource/path/PathSetTest.java index 734eadd..4704443 100644 --- a/src/test/java/org/apache/sling/api/resource/path/PathSetTest.java +++ b/src/test/java/org/apache/sling/api/resource/path/PathSetTest.java @@ -113,6 +113,16 @@ public class PathSetTest { assertEquals(new Path("/x/y"), set.matches("/x/y/g/e")); } + @Test + public void testGlobArgumentProducesIncorrectContainmentResult() { + final PathSet set = PathSet.fromStrings("/apps"); + + // Document known incorrect containment behavior inherited from Path.matches(). + assertEquals(new Path("/apps"), set.matches("glob:/**")); + assertEquals(new Path("/apps"), set.matches("glob:/apps/**")); + assertNull(set.matches("/etc/secret")); + } + @Test public void testToStringSet() { final PathSet set = PathSet.fromStrings("/a", "/x/y"); diff --git a/src/test/java/org/apache/sling/api/resource/path/PathTest.java b/src/test/java/org/apache/sling/api/resource/path/PathTest.java index 0450693..f35c7ec 100644 --- a/src/test/java/org/apache/sling/api/resource/path/PathTest.java +++ b/src/test/java/org/apache/sling/api/resource/path/PathTest.java @@ -63,6 +63,16 @@ public class PathTest { assertMatch(p, "/content", "/content/a", "/content/a/b"); } + @Test + public void testGlobArgumentProducesIncorrectContainmentResult() { + final Path path = new Path("/apps"); + + // Document known incorrect containment behavior, not a desired membership result. + assertTrue(path.matches("glob:/**")); + assertTrue(path.matches("glob:/apps/**")); + assertFalse(path.matches("/etc/secret")); + } + @Test public void testPatternMatchingA() { final Path p = new Path("glob:/apps/**/*.html");
