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

elecharny pushed a commit to branch 2.0.X
in repository https://gitbox.apache.org/repos/asf/mina.git

commit 8b1dadb55b1d3f6b17f4ded10179e6b253ff1cc9
Author: Emmanuel Lécharny <[email protected]>
AuthorDate: Thu Apr 23 10:51:03 2026 +0200

    Added patch regarding whitelist bypassing backported from mina-2.2.X
---
 .../apache/mina/core/buffer/AbstractIoBuffer.java  | 47 ++++++------
 .../org/apache/mina/core/buffer/IoBufferTest.java  | 88 +++++++++++++++++++---
 2 files changed, 103 insertions(+), 32 deletions(-)

diff --git 
a/mina-core/src/main/java/org/apache/mina/core/buffer/AbstractIoBuffer.java 
b/mina-core/src/main/java/org/apache/mina/core/buffer/AbstractIoBuffer.java
index 1a2463a6a..d5d54f9e5 100644
--- a/mina-core/src/main/java/org/apache/mina/core/buffer/AbstractIoBuffer.java
+++ b/mina-core/src/main/java/org/apache/mina/core/buffer/AbstractIoBuffer.java
@@ -88,6 +88,7 @@ public abstract class AbstractIoBuffer extends IoBuffer {
     /** A mask for an int */
     private static final long INT_MASK = 0xFFFFFFFFL;
 
+    /** A list of acceptable classes for deserialization */
     private final List<ClassNameMatcher> acceptMatchers = new ArrayList<>();
 
     /**
@@ -2182,6 +2183,14 @@ public abstract class AbstractIoBuffer extends IoBuffer {
 
                     case 1: // Serializable class
                         String className = readUTF();
+
+                        // Only accept classes that are listed as acceptable
+                        // Apply class filter BEFORE calling Class.forName
+                        if (!acceptMatchers.stream().anyMatch(m -> 
m.matches(className))) {
+                            throw new ClassNotFoundException("Class not in 
accept list " + className);
+                        }
+
+                        // Use initialize=false to prevent static block 
execution during class loading
                         Class<?> clazz = Class.forName(className, true, 
classLoader);
 
                         return ObjectStreamClass.lookup(clazz);
@@ -2193,32 +2202,24 @@ public abstract class AbstractIoBuffer extends IoBuffer 
{
 
             @Override
             protected Class<?> resolveClass(ObjectStreamClass desc) throws 
IOException, ClassNotFoundException {
-                Class<?> clazz = desc.forClass();
+                String className = desc.getName();
                     
-                if (clazz == null) {
-                    String name = desc.getName();
+                // apply acceptMatchers filter before any Class.forName() call,
+                // regardless of whether forClass() is null or not
+                if (!acceptMatchers.stream().anyMatch(m -> 
m.matches(className))) {
+                    throw new ClassNotFoundException("Class not in accept list 
" + className);
+                }
+    
+                Class<?> clazz = desc.forClass();
 
-                    try {
-                        return Class.forName(name, false, classLoader);
-                    } catch (ClassNotFoundException ex) {
-                        return super.resolveClass(desc);
-                    }
-                } else {
-                    boolean found = false;
-                    String className = desc.getName();
-                    
-                    for (ClassNameMatcher matcher : acceptMatchers) {
-                        if (matcher.matches(className)) {
-                            found = true;
-                            break;
-                        }
-                    }
+                if (clazz != null) {
+                    return clazz;
+                }
 
-                    if (found) {
-                        return clazz;
-                    }
-                    
-                    throw new ClassNotFoundException();
+                try {
+                    return Class.forName(className, false, classLoader);
+                } catch (ClassNotFoundException ex) {
+                    return super.resolveClass(desc);
                 }
             }
         }) {
diff --git 
a/mina-core/src/test/java/org/apache/mina/core/buffer/IoBufferTest.java 
b/mina-core/src/test/java/org/apache/mina/core/buffer/IoBufferTest.java
index e969428a4..04c792afd 100644
--- a/mina-core/src/test/java/org/apache/mina/core/buffer/IoBufferTest.java
+++ b/mina-core/src/test/java/org/apache/mina/core/buffer/IoBufferTest.java
@@ -44,6 +44,7 @@ import java.util.List;
 import org.apache.mina.core.buffer.matcher.RegexpClassNameMatcher;
 import org.apache.mina.core.buffer.matcher.WildcardClassNameMatcher;
 import org.apache.mina.util.Bar;
+import org.apache.mina.util.Foo;
 import org.junit.Test;
 
 /**
@@ -53,10 +54,10 @@ import org.junit.Test;
  */
 public class IoBufferTest {
 
-    private static interface NonserializableInterface {
+    private static interface NonSerializableInterface {
     }
 
-    public static class NonserializableClass {
+    public static class NonSerializableClass {
     }
 
     /**
@@ -388,8 +389,29 @@ public class IoBufferTest {
         assertNotSame(o, o2);
     }
 
+    @Test(expected=ClassNotFoundException.class)
+    public void testObjectSerializationReject() throws Exception {
+        IoBuffer buf = IoBuffer.allocate(16);
+        buf.setAutoExpand(true);
+        List<Object> o = new ArrayList<>();
+        o.add(new Date());
+        o.add(long.class);
+
+        // We don't accept type 0 class (long)
+        buf.accept(ArrayList.class.getName(), Date.class.getName());
+
+        // Test writing an object.
+        buf.putObject(o);
+
+        // Test reading an object.
+        buf.clear();
+
+        // The call should fail as long is not accepted
+        buf.getObject();
+    }
+
     @Test
-    public void testNonserializableClass() throws Exception {
+    public void testSerializableClass() throws Exception {
         Class<?> c = String.class;
 
         IoBuffer buffer = IoBuffer.allocate(16);
@@ -407,7 +429,7 @@ public class IoBufferTest {
     }
 
     @Test
-    public void testNonserializableClassAcceptWildcard() throws Exception {
+    public void testSerializableClassAcceptWildcard() throws Exception {
         Class<?> c = String.class;
 
         IoBuffer buffer = IoBuffer.allocate(16);
@@ -444,8 +466,8 @@ public class IoBufferTest {
         assertSame(c, o);
     }
 
-    @Test(expected=ClassNotFoundException.class)
-    public void testNonserializableClassReject() throws Exception {
+    @Test(expected=BufferDataException.class)
+    public void testSerializableClassReject() throws Exception {
         Class<?> c = String.class;
 
         IoBuffer buffer = IoBuffer.allocate(16);
@@ -460,13 +482,43 @@ public class IoBufferTest {
     }
 
     @Test
-    public void testNonserializableInterface() throws Exception {
-        Class<?> c = NonserializableInterface.class;
+    public void testNonserializableInterfaceAccept() throws Exception {
+        Class<?> c = NonSerializableInterface.class;
+
+        IoBuffer buffer = IoBuffer.allocate(16);
+        buffer.setAutoExpand(true);
+        buffer.putObject(c);
+        buffer.accept(NonSerializableInterface.class.getName());
+
+        buffer.flip();
+        Object o = buffer.getObject();
+
+        assertEquals(c, o);
+        assertSame(c, o);
+    }
+
+    @Test(expected=ClassNotFoundException.class)
+    public void testNonserializableInterfaceReject() throws Exception {
+        Class<?> c = NonSerializableInterface.class;
+
+        IoBuffer buffer = IoBuffer.allocate(16);
+        buffer.setAutoExpand(true);
+        buffer.putObject(c);
+
+        buffer.flip();
+
+        // We must get an error
+        buffer.getObject();
+    }
+
+    @Test
+    public void testNonserializableClassAccept() throws Exception {
+        Class<?> c = NonSerializableClass.class;
 
         IoBuffer buffer = IoBuffer.allocate(16);
         buffer.setAutoExpand(true);
         buffer.putObject(c);
-        buffer.accept(NonserializableInterface.class.getName());
+        buffer.accept(NonSerializableClass.class.getName());
 
         buffer.flip();
         Object o = buffer.getObject();
@@ -475,6 +527,21 @@ public class IoBufferTest {
         assertSame(c, o);
     }
 
+
+    @Test(expected=ClassNotFoundException.class)
+    public void testNonserializableClassReject() throws Exception {
+        Class<?> c = NonSerializableClass.class;
+
+        IoBuffer buffer = IoBuffer.allocate(16);
+        buffer.setAutoExpand(true);
+        buffer.putObject(c);
+
+        buffer.flip();
+
+        // The call must fail
+        buffer.getObject();
+    }
+
     @Test
     public void testAllocate() throws Exception {
         for (int i = 10; i < 1048576 * 2; i = i * 11 / 10) // increase by 10%
@@ -1007,7 +1074,10 @@ public class IoBufferTest {
 
         // Test writing an object.
         buf.putObject(expected);
+
+        // We must accept all the classes, including the parents.
         buf.accept(Bar.class.getName());
+        buf.accept(Foo.class.getName());
 
         // Test reading an object.
         buf.clear();

Reply via email to