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

cziegeler 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 923c461  SLING-13065 : SlingUriBuilder parse results in 
java.lang.StringIndexOutOfBoundsException (#78)
923c461 is described below

commit 923c461a48888b565185f94c0a355497d760f552
Author: Carsten Ziegeler <[email protected]>
AuthorDate: Mon Jun 1 07:03:58 2026 +0200

    SLING-13065 : SlingUriBuilder parse results in 
java.lang.StringIndexOutOfBoundsException (#78)
    
    * SLING-13065 : SlingUriBuilder parse results in 
java.lang.StringIndexOutOfBoundsException
    
    Co-authored-by: Copilot <[email protected]>
    
    * Potential fix for pull request finding
    
    Co-authored-by: Copilot Autofix powered by AI 
<[email protected]>
    
    ---------
    
    Co-authored-by: Copilot <[email protected]>
    Co-authored-by: Copilot Autofix powered by AI 
<[email protected]>
---
 .../org/apache/sling/api/uri/SlingUriBuilder.java  |  7 +++
 .../apache/sling/api/uri/SlingUriRebaseTest.java   | 61 ++++++++++++++++++++++
 2 files changed, 68 insertions(+)

diff --git a/src/main/java/org/apache/sling/api/uri/SlingUriBuilder.java 
b/src/main/java/org/apache/sling/api/uri/SlingUriBuilder.java
index 582b925..ac48dd1 100644
--- a/src/main/java/org/apache/sling/api/uri/SlingUriBuilder.java
+++ b/src/main/java/org/apache/sling/api/uri/SlingUriBuilder.java
@@ -447,6 +447,13 @@ public class SlingUriBuilder {
         suffix = null;
         if (availableResourcePath.length() == path.length()) {
             resourcePath = availableResourcePath;
+        } else if (availableResourcePath.length() + 1 == path.length()
+                && path.charAt(availableResourcePath.length()) == '/') {
+            // The path has a trailing slash that is not part of the resource 
path (e.g.
+            // /apidocs/sling12/ with resource at /apidocs/sling12). 
setPathWithDefinedResourcePosition
+            // assumes a dot separator at the given position; a trailing slash 
must be handled here
+            // to avoid StringIndexOutOfBoundsException.
+            resourcePath = availableResourcePath;
         } else {
             setPathWithDefinedResourcePosition(path, 
availableResourcePath.length());
         }
diff --git a/src/test/java/org/apache/sling/api/uri/SlingUriRebaseTest.java 
b/src/test/java/org/apache/sling/api/uri/SlingUriRebaseTest.java
index 0c985f1..1a053c7 100644
--- a/src/test/java/org/apache/sling/api/uri/SlingUriRebaseTest.java
+++ b/src/test/java/org/apache/sling/api/uri/SlingUriRebaseTest.java
@@ -18,6 +18,7 @@
  */
 package org.apache.sling.api.uri;
 
+import java.net.URI;
 import java.net.URISyntaxException;
 
 import org.apache.sling.api.resource.Resource;
@@ -29,6 +30,8 @@ import org.mockito.junit.MockitoJUnitRunner;
 
 import static org.apache.sling.api.uri.SlingUriTest.testUri;
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
 import static org.mockito.Mockito.when;
 
 @RunWith(MockitoJUnitRunner.Silent.class)
@@ -310,4 +313,62 @@ public class SlingUriRebaseTest {
         String testPath = "/path/to/page.html";
         SlingUriBuilder.parse(testPath, null).rebaseResourcePath().build();
     }
+
+    @Test
+    public void testRebaseResourcePathWithTrailingSlashResourceExists() {
+        // path with trailing slash, resource exists at path without trailing 
slash
+        when(resolver.getResource("/apidocs/sling12")).thenReturn(resource);
+        SlingUri slingUri = SlingUriBuilder.parse("/apidocs/sling12/", 
resolver).build();
+        assertNotNull(slingUri);
+        assertEquals("/apidocs/sling12", slingUri.getResourcePath());
+        assertNull(slingUri.getSelectorString());
+        assertNull(slingUri.getExtension());
+        assertNull(slingUri.getSuffix());
+    }
+
+    @Test
+    public void testRebaseResourcePathWithTrailingSlashNoResourceExists() {
+        // path with trailing slash, no resource exists: should not throw 
StringIndexOutOfBoundsException
+        when(resolver.getResource("/apidocs/sling12")).thenReturn(null);
+        SlingUri slingUri = SlingUriBuilder.parse("/apidocs/sling12/", 
resolver).build();
+        assertNotNull(slingUri);
+    }
+
+    @Test
+    public void testRebaseFullUriWithTrailingSlash() throws URISyntaxException 
{
+        // full external URI with trailing slash path - the original bug 
report scenario
+        // No StringIndexOutOfBoundsException should be thrown
+        SlingUri slingUri = 
SlingUriBuilder.parse("https://sling.apache.org/apidocs/sling12/";, resolver)
+                .build();
+        assertNotNull(slingUri);
+        assertEquals("https", slingUri.getScheme());
+        assertEquals("sling.apache.org", slingUri.getHost());
+    }
+
+    @Test
+    public void testRebaseCreateFromUriWithTrailingSlash() throws 
URISyntaxException {
+        // createFrom(URI, resolver) with trailing slash path - the original 
bug report scenario
+        // No StringIndexOutOfBoundsException should be thrown
+        URI input = new URI("https://sling.apache.org/apidocs/sling12/";);
+        SlingUri slingUri = SlingUriBuilder.createFrom(input, 
resolver).build();
+        assertNotNull(slingUri);
+        assertEquals("https", slingUri.getScheme());
+        assertEquals("sling.apache.org", slingUri.getHost());
+    }
+
+    @Test
+    public void testRebaseResourcePathWithSlashSuffix() {
+        // For /content/page.html/suffix, the iterator strips the suffix then 
the .html extension,
+        // landing at /content/page; then setPathWithDefinedResourcePosition 
splits at '.' giving
+        // extension=html, suffix=/suffix.
+        
when(resolver.getResource("/content/page.html/suffix")).thenReturn(null);
+        when(resolver.getResource("/content/page")).thenReturn(resource);
+        SlingUri slingUri =
+                SlingUriBuilder.parse("/content/page.html/suffix", 
resolver).build();
+        assertNotNull(slingUri);
+        assertEquals("/content/page", slingUri.getResourcePath());
+        assertEquals(null, slingUri.getSelectorString());
+        assertEquals("html", slingUri.getExtension());
+        assertEquals("/suffix", slingUri.getSuffix());
+    }
 }

Reply via email to