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