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

garydgregory pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/commons-bcel.git


The following commit(s) were added to refs/heads/master by this push:
     new 5262b90c reject caload on non-char arrays in structural verification 
(#522)
5262b90c is described below

commit 5262b90cd95b1c9d288c257ea726c777437728f3
Author: Naveed Khan <[email protected]>
AuthorDate: Tue Jul 14 18:13:33 2026 +0000

    reject caload on non-char arrays in structural verification (#522)
    
    visitCALOAD only checked that the arrayref is an array, never that its 
component type is char, so Pass3b accepted caload on any array such as int[] or 
a reference array. Add the char component check that the sibling visitCASTORE 
already performs.
---
 .../structurals/InstConstraintVisitor.java         |  5 +-
 .../bcel/verifier/VerifierArrayAccessTest.java     |  3 +
 .../verifier/tests/TestArrayAccess06Creator.java   | 91 ++++++++++++++++++++++
 3 files changed, 98 insertions(+), 1 deletion(-)

diff --git 
a/src/main/java/org/apache/bcel/verifier/structurals/InstConstraintVisitor.java 
b/src/main/java/org/apache/bcel/verifier/structurals/InstConstraintVisitor.java
index 40481fbe..e27ac7dc 100644
--- 
a/src/main/java/org/apache/bcel/verifier/structurals/InstConstraintVisitor.java
+++ 
b/src/main/java/org/apache/bcel/verifier/structurals/InstConstraintVisitor.java
@@ -404,7 +404,10 @@ public class InstConstraintVisitor extends EmptyVisitor {
         final Type index = stack().peek(0);
 
         indexOfInt(o, index);
-        arrayrefOfArrayType(o, arrayref);
+        if (arrayrefOfArrayType(o, arrayref) && !((ArrayType) 
arrayref).getElementType().equals(Type.CHAR)) {
+            constraintViolated(o, "The 'arrayref' does not refer to an array 
with elements of type char but to an array of type "
+                + ((ArrayType) arrayref).getElementType() + ".");
+        }
     }
 
     /**
diff --git 
a/src/test/java/org/apache/bcel/verifier/VerifierArrayAccessTest.java 
b/src/test/java/org/apache/bcel/verifier/VerifierArrayAccessTest.java
index 3f96b04e..0cebe131 100644
--- a/src/test/java/org/apache/bcel/verifier/VerifierArrayAccessTest.java
+++ b/src/test/java/org/apache/bcel/verifier/VerifierArrayAccessTest.java
@@ -32,6 +32,7 @@ import 
org.apache.bcel.verifier.tests.TestArrayAccess04LongCreator;
 import org.apache.bcel.verifier.tests.TestArrayAccess04ShortCreator;
 import org.apache.bcel.verifier.tests.TestArrayAccess04UnknownCreator;
 import org.apache.bcel.verifier.tests.TestArrayAccess05Creator;
+import org.apache.bcel.verifier.tests.TestArrayAccess06Creator;
 import org.junit.jupiter.api.Test;
 
 class VerifierArrayAccessTest extends AbstractVerifierTest {
@@ -54,6 +55,8 @@ class VerifierArrayAccessTest extends AbstractVerifierTest {
         assertThrowsExactly(IllegalArgumentException.class, 
testArrayAccess04UnknownCreator::create, "Invalid type <unknown object>");
         new TestArrayAccess05Creator().create();
         assertVerifyRejected("TestArrayAccess05", "Verification of iaload 
applied to a multidimensional int[][] must fail.");
+        new TestArrayAccess06Creator().create();
+        assertVerifyRejected("TestArrayAccess06", "Verification of caload 
applied to an int[] must fail.");
     }
 
     @Test
diff --git 
a/src/test/java/org/apache/bcel/verifier/tests/TestArrayAccess06Creator.java 
b/src/test/java/org/apache/bcel/verifier/tests/TestArrayAccess06Creator.java
new file mode 100644
index 00000000..587535b4
--- /dev/null
+++ b/src/test/java/org/apache/bcel/verifier/tests/TestArrayAccess06Creator.java
@@ -0,0 +1,91 @@
+/*
+ * 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
+ *
+ *   https://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.bcel.verifier.tests;
+
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+import org.apache.bcel.Const;
+import org.apache.bcel.generic.ClassGen;
+import org.apache.bcel.generic.ConstantPoolGen;
+import org.apache.bcel.generic.InstructionConst;
+import org.apache.bcel.generic.InstructionFactory;
+import org.apache.bcel.generic.InstructionHandle;
+import org.apache.bcel.generic.InstructionList;
+import org.apache.bcel.generic.MethodGen;
+import org.apache.bcel.generic.PUSH;
+import org.apache.bcel.generic.Type;
+
+/**
+ * Emits a method that applies {@code caload} to an {@code int[]} reference. 
The {@code caload} instruction requires a
+ * {@code char[]}, so applying it to an array with a different component type 
is illegal and structural verification must
+ * reject it.
+ */
+public class TestArrayAccess06Creator extends TestCreator {
+    private final InstructionFactory factory;
+    private final ConstantPoolGen cp;
+    private final ClassGen cg;
+
+    public TestArrayAccess06Creator() {
+        cg = new ClassGen(TEST_PACKAGE + ".TestArrayAccess06", 
"java.lang.Object", "TestArrayAccess06.java", Const.ACC_PUBLIC | 
Const.ACC_SUPER,
+            new String[] {});
+        cp = cg.getConstantPool();
+        factory = new InstructionFactory(cg, cp);
+    }
+
+    @Override
+    public void create(final OutputStream out) throws IOException {
+        createMethod_0();
+        createMethod_1();
+        cg.getJavaClass().dump(out);
+    }
+
+    private void createMethod_0() {
+        final InstructionList il = new InstructionList();
+        final MethodGen method = new MethodGen(Const.ACC_PUBLIC, Type.VOID, 
Type.NO_ARGS, new String[] {}, "<init>", TEST_PACKAGE + ".TestArrayAccess06", 
il, cp);
+        il.append(InstructionFactory.createLoad(Type.OBJECT, 0));
+        il.append(factory.createInvoke("java.lang.Object", "<init>", 
Type.VOID, Type.NO_ARGS, Const.INVOKESPECIAL));
+        il.append(InstructionFactory.createReturn(Type.VOID));
+        method.setMaxStack();
+        method.setMaxLocals();
+        cg.addMethod(method.getMethod());
+        il.dispose();
+    }
+
+    private void createMethod_1() {
+        final InstructionList il = new InstructionList();
+        final MethodGen method = new MethodGen(Const.ACC_PUBLIC | 
Const.ACC_STATIC, Type.VOID, Type.NO_ARGS, new String[] {}, "test",
+            TEST_PACKAGE + ".TestArrayAccess06", il, cp);
+
+        il.append(new PUSH(cp, 1));
+        il.append(factory.createNewArray(Type.INT, (short) 1)); // int[]
+        il.append(new PUSH(cp, 0));
+        il.append(InstructionConst.CALOAD); // caload on int[] is illegal
+        il.append(InstructionConst.POP);
+        final InstructionHandle ihReturn = 
il.append(InstructionFactory.createReturn(Type.VOID));
+        assertNotNull(ihReturn);
+        method.setMaxStack();
+        method.setMaxLocals();
+        cg.addMethod(method.getMethod());
+        il.dispose();
+    }
+}

Reply via email to