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");

Reply via email to