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-rewriter.git


The following commit(s) were added to refs/heads/master by this push:
     new 26976e1  SLING-12308 : Potential ArrayIndexOutOfBoundsException with 
global transformers
26976e1 is described below

commit 26976e1b370ef2734428dc80ba3ae2fec3f0351b
Author: Carsten Ziegeler <[email protected]>
AuthorDate: Tue Apr 30 11:01:18 2024 +0200

    SLING-12308 : Potential ArrayIndexOutOfBoundsException with global 
transformers
---
 .../apache/sling/rewriter/impl/FactoryCache.java   | 12 +--
 .../rewriter/impl/ProcessorConfigurationImpl.java  | 29 ++++---
 .../impl/TransformerFactoryServiceTracker.java     | 14 ++--
 .../sling/rewriter/impl/FactoryCacheTest.java      | 95 ++++++++++++++++++++++
 4 files changed, 125 insertions(+), 25 deletions(-)

diff --git a/src/main/java/org/apache/sling/rewriter/impl/FactoryCache.java 
b/src/main/java/org/apache/sling/rewriter/impl/FactoryCache.java
index 8d7331b..90cd237 100644
--- a/src/main/java/org/apache/sling/rewriter/impl/FactoryCache.java
+++ b/src/main/java/org/apache/sling/rewriter/impl/FactoryCache.java
@@ -201,9 +201,9 @@ public class FactoryCache {
      * @param factories The transformer factories
      * @return The transformer instances
      */
-    private Transformer[][] createTransformers(final TransformerFactory[][] 
factories) {
-        if ( factories == EMPTY_DOUBLE_ARRAY ) {
-            return FactoryCache.EMPTY_DOUBLE_ARRAY;
+    Transformer[][] createTransformers(final TransformerFactory[][] factories) 
{
+        if ( factories == 
TransformerFactoryServiceTracker.EMPTY_DOUBLE_FACTORY_ARRAY ) {
+            return EMPTY_DOUBLE_ARRAY;
         }
         final Transformer[][] transformers = new Transformer[2][];
         for(int arrayIndex = 0; arrayIndex < 2; arrayIndex++) {
@@ -212,13 +212,15 @@ public class FactoryCache {
                 if ( factory == null ) count--;
             }
             if ( count == 0 ) {
-                transformers[arrayIndex] = FactoryCache.EMPTY_ARRAY;
+                transformers[arrayIndex] = EMPTY_ARRAY;
             } else {
                 transformers[arrayIndex] = new Transformer[count];
+                int tIndex = 0;
                 for(int i=0; i < factories[arrayIndex].length; i++) {
                     final TransformerFactory factory = 
factories[arrayIndex][i];
                     if ( factory != null ) {
-                        transformers[arrayIndex][i] = 
factory.createTransformer();
+                        transformers[arrayIndex][tIndex] = 
factory.createTransformer();
+                        tIndex++;
                     }
                 }
             }
diff --git 
a/src/main/java/org/apache/sling/rewriter/impl/ProcessorConfigurationImpl.java 
b/src/main/java/org/apache/sling/rewriter/impl/ProcessorConfigurationImpl.java
index df5f036..33a790e 100644
--- 
a/src/main/java/org/apache/sling/rewriter/impl/ProcessorConfigurationImpl.java
+++ 
b/src/main/java/org/apache/sling/rewriter/impl/ProcessorConfigurationImpl.java
@@ -217,7 +217,7 @@ public class ProcessorConfigurationImpl implements 
PipelineConfiguration {
         pw.println(this.processErrorResponse);
         pw.print("Order : ");
         pw.println(this.order);
-    if (this.name != null) {
+        if (this.name != null) {
             pw.print("Active : ");
             pw.println(this.isActive);
             pw.print("Valid : ");
@@ -281,10 +281,9 @@ public class ProcessorConfigurationImpl implements 
PipelineConfiguration {
         }
         sb.append("processErrorResponse=");
         sb.append(this.processErrorResponse);
-        sb.append(", ");
+        sb.append(", order=");
+        sb.append(this.order);
         if (this.name != null) {
-            sb.append("order=");
-            sb.append(this.order);
             sb.append(", active=");
             sb.append(this.isActive);
             sb.append(", valid=");
@@ -407,17 +406,17 @@ public class ProcessorConfigurationImpl implements 
PipelineConfiguration {
         // now check extenstions
         // if no extenstion is configured, we apply to all extenstions
         if ( this.extensions != null && this.extensions.length > 0 ) {
-             boolean found = false;
-             int index = 0;
-             while ( !found && index < this.extensions.length ) {
-                 if ( 
this.extensions[index].equals(processContext.getRequest().getRequestPathInfo().getExtension())
 ) {
-                     found = true;
-                 }
-                 index++;
-             }
-             if ( !found ) {
-                 return false;
-             }
+            boolean found = false;
+            int index = 0;
+            while ( !found && index < this.extensions.length ) {
+                if ( 
this.extensions[index].equals(processContext.getRequest().getRequestPathInfo().getExtension())
 ) {
+                    found = true;
+                }
+                index++;
+            }
+            if ( !found ) {
+                return false;
+            }
         }
         // check resource types
         if ( this.resourceTypes != null && this.resourceTypes.length > 0 ) {
diff --git 
a/src/main/java/org/apache/sling/rewriter/impl/TransformerFactoryServiceTracker.java
 
b/src/main/java/org/apache/sling/rewriter/impl/TransformerFactoryServiceTracker.java
index 45f0cc7..5e996ef 100644
--- 
a/src/main/java/org/apache/sling/rewriter/impl/TransformerFactoryServiceTracker.java
+++ 
b/src/main/java/org/apache/sling/rewriter/impl/TransformerFactoryServiceTracker.java
@@ -125,12 +125,16 @@ final class TransformerFactoryServiceTracker extends 
HashingServiceTrackerCustom
                         int index = 0;
                         for(final ServiceReference<TransformerFactory> ref : 
refs) {
                             if ( isGlobal(ref) ) {
-                                if ( index < preCount ) {
-                                    LOGGER.debug("Initializing pre global 
TransformerFactory for service ref: {}", ref.getClass());
-                                    globalFactories[0][index] = new 
TransformerFactoryEntry(this.getService(ref), ref);
+                                LOGGER.debug("Initializing {} global 
TransformerFactory for service ref: {}", index < preCount ? "pre" : "post", 
ref.getClass());
+                                final TransformerFactory factory = 
this.getService(ref);
+                                if ( factory == null) {
+                                    LOGGER.debug("TransformerFactory is null 
for service ref: {}", ref);
                                 } else {
-                                    LOGGER.debug("Initializing post global 
TransformerFactory for service ref: {}", ref.getClass());
-                                    globalFactories[1][index - preCount] = new 
TransformerFactoryEntry(this.getService(ref), ref);
+                                    if ( index < preCount ) {
+                                        globalFactories[0][index] = new 
TransformerFactoryEntry(factory, ref);
+                                    } else {
+                                        globalFactories[1][index - preCount] = 
new TransformerFactoryEntry(factory, ref);
+                                    }
                                 }
                                 index++;
                             }
diff --git a/src/test/java/org/apache/sling/rewriter/impl/FactoryCacheTest.java 
b/src/test/java/org/apache/sling/rewriter/impl/FactoryCacheTest.java
new file mode 100644
index 0000000..f9f11a9
--- /dev/null
+++ b/src/test/java/org/apache/sling/rewriter/impl/FactoryCacheTest.java
@@ -0,0 +1,95 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with this
+ * work for additional information regarding copyright ownership. The ASF
+ * licenses this file to You under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations 
under
+ * the License.
+ */
+package org.apache.sling.rewriter.impl;
+
+import static org.junit.Assert.assertEquals;
+
+import org.apache.sling.rewriter.Transformer;
+import org.apache.sling.rewriter.TransformerFactory;
+import org.junit.Test;
+import org.mockito.Mockito;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.InvalidSyntaxException;
+
+public class FactoryCacheTest {
+
+    @Test
+    public void testCreateTransformers() throws InvalidSyntaxException {
+        final BundleContext bc = Mockito.mock(BundleContext.class);
+        final FactoryCache cache = new FactoryCache(bc);
+
+        final TransformerFactory tf1 = Mockito.mock(TransformerFactory.class);
+        final Transformer t1 = Mockito.mock(Transformer.class);
+        Mockito.when(tf1.createTransformer()).thenReturn(t1);
+
+        // empty double array
+        Transformer[][] result = 
cache.createTransformers(TransformerFactoryServiceTracker.EMPTY_DOUBLE_FACTORY_ARRAY);
+        assertEquals(2, result.length);
+        assertEquals(0, result[0].length);
+        assertEquals(0, result[1].length);
+
+        // first empty second t1
+        final TransformerFactory[][] factories = new TransformerFactory[][] { 
TransformerFactoryServiceTracker.EMPTY_FACTORY_ARRAY, new TransformerFactory[] 
{ tf1 } };
+        result = cache.createTransformers(factories);
+        assertEquals(2, result.length);
+        assertEquals(0, result[0].length);
+        assertEquals(1, result[1].length);
+        assertEquals(t1, result[1][0]);
+
+        // first t1 second empty
+        final TransformerFactory[][] factories2 = new TransformerFactory[][] { 
new TransformerFactory[] { tf1 }, 
TransformerFactoryServiceTracker.EMPTY_FACTORY_ARRAY };
+        result = cache.createTransformers(factories2);
+        assertEquals(2, result.length);
+        assertEquals(1, result[0].length);
+        assertEquals(0, result[1].length);
+        assertEquals(t1, result[0][0]);
+
+        // first t1 second t1
+        final TransformerFactory[][] factories3 = new TransformerFactory[][] { 
new TransformerFactory[] { tf1 }, new TransformerFactory[] { tf1 } };
+        result = cache.createTransformers(factories3);
+        assertEquals(2, result.length);
+        assertEquals(1, result[0].length);
+        assertEquals(1, result[1].length);
+        assertEquals(t1, result[0][0]);
+        assertEquals(t1, result[1][0]);
+
+        // create second transformer factory
+        final TransformerFactory tf2 = Mockito.mock(TransformerFactory.class);
+        final Transformer t2 = Mockito.mock(Transformer.class);
+        Mockito.when(tf2.createTransformer()).thenReturn(t2);
+
+        // first t1 and t2, second t2 and t1
+        final TransformerFactory[][] factories4 = new TransformerFactory[][] { 
new TransformerFactory[] { tf1, tf2 }, new TransformerFactory[] { tf2, tf1 } };
+        result = cache.createTransformers(factories4);
+        assertEquals(2, result.length);
+        assertEquals(2, result[0].length);
+        assertEquals(2, result[1].length);
+        assertEquals(t1, result[0][0]);
+        assertEquals(t2, result[0][1]);
+        assertEquals(t2, result[1][0]);
+        assertEquals(t1, result[1][1]);
+
+        // first t1 and null, second null and t1
+        final TransformerFactory[][] factories5 = new TransformerFactory[][] { 
new TransformerFactory[] { tf1, null }, new TransformerFactory[] { null, tf1 } 
};
+        result = cache.createTransformers(factories5);
+        assertEquals(2, result.length);
+        assertEquals(1, result[0].length);
+        assertEquals(1, result[1].length);
+        assertEquals(t1, result[0][0]);
+        assertEquals(t1, result[1][0]);
+    }
+}

Reply via email to