This is an automated email from the ASF dual-hosted git repository.

joerghoh pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-api.git


The following commit(s) were added to refs/heads/master by this push:
     new e6ca83d  SLING-13380 document existing (incorrect) behavior of 
Path.matches() and PathSet.matches() (#86)
e6ca83d is described below

commit e6ca83dae1beab250e85c476fc5d5c9282893b4b
Author: Jörg Hoh <[email protected]>
AuthorDate: Fri Oct 9 17:19:54 2026 +0200

    SLING-13380 document existing (incorrect) behavior of Path.matches() and 
PathSet.matches() (#86)
---
 src/main/java/org/apache/sling/api/resource/path/Path.java     | 10 ++++++++++
 src/main/java/org/apache/sling/api/resource/path/PathSet.java  |  8 ++++++++
 .../java/org/apache/sling/api/resource/path/PathSetTest.java   | 10 ++++++++++
 src/test/java/org/apache/sling/api/resource/path/PathTest.java | 10 ++++++++++
 4 files changed, 38 insertions(+)

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 a83b732..27b30c8 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
@@ -122,6 +122,16 @@ public class Path implements Comparable<Path> {
      * 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
      *         or matches the pattern.
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 f7b389a..4dcbf3f 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
@@ -133,6 +133,14 @@ public class PathSet implements Iterable<Path> {
      * Concrete path arguments are normalized before matching; paths that
      * cannot be normalized do not match. Glob pattern arguments retain their
      * pattern semantics.
+     *
+     * <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 3c3e1bc..d59b612 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
@@ -210,6 +210,16 @@ public class PathSetTest {
         assertNotNull(set.matches("/etc/secret/value"));
     }
 
+    @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 10062ed..6a05926 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
@@ -148,6 +148,16 @@ public class PathTest {
         assertMatch(glob, "/apps/..", "//apps//foo", "/apps/.");
     }
 
+    @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