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 2aef1be6 use array element type not basic type for primitive array 
access (#520)
2aef1be6 is described below

commit 2aef1be6546ed79cae003dfc0eefd864c211be80
Author: Naveed Khan <[email protected]>
AuthorDate: Sun Jul 12 02:03:01 2026 +0000

    use array element type not basic type for primitive array access (#520)
    
    getBasicType() drops the dimension count, so iaload on int[][] passed 
structural verification even though its component type is a reference; the ten 
primitive *aload/*astore constraints in InstConstraintVisitor now use 
getElementType() like the reference and byte/char siblings.
---
 .../structurals/InstConstraintVisitor.java         | 20 ++---
 .../bcel/verifier/VerifierArrayAccessTest.java     |  3 +
 .../verifier/tests/TestArrayAccess05Creator.java   | 92 ++++++++++++++++++++++
 3 files changed, 105 insertions(+), 10 deletions(-)

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 34c7f19a..40481fbe 100644
--- 
a/src/main/java/org/apache/bcel/verifier/structurals/InstConstraintVisitor.java
+++ 
b/src/main/java/org/apache/bcel/verifier/structurals/InstConstraintVisitor.java
@@ -518,7 +518,7 @@ public class InstConstraintVisitor extends EmptyVisitor {
         if (!(stack().peek(1) instanceof ArrayType)) {
             constraintViolated(o, "Stack next-to-top must be of type double[] 
but is '" + stack().peek(1) + "'.");
         }
-        final Type t = ((ArrayType) stack().peek(1)).getBasicType();
+        final Type t = ((ArrayType) stack().peek(1)).getElementType();
         if (t != Type.DOUBLE) {
             constraintViolated(o, "Stack next-to-top must be of type double[] 
but is '" + stack().peek(1) + "'.");
         }
@@ -539,7 +539,7 @@ public class InstConstraintVisitor extends EmptyVisitor {
         if (!(stack().peek(2) instanceof ArrayType)) {
             constraintViolated(o, "Stack next-to-next-to-top must be of type 
double[] but is '" + stack().peek(2) + "'.");
         }
-        final Type t = ((ArrayType) stack().peek(2)).getBasicType();
+        final Type t = ((ArrayType) stack().peek(2)).getElementType();
         if (t != Type.DOUBLE) {
             constraintViolated(o, "Stack next-to-next-to-top must be of type 
double[] but is '" + stack().peek(2) + "'.");
         }
@@ -825,7 +825,7 @@ public class InstConstraintVisitor extends EmptyVisitor {
         if (!(stack().peek(1) instanceof ArrayType)) {
             constraintViolated(o, "Stack next-to-top must be of type float[] 
but is '" + stack().peek(1) + "'.");
         }
-        final Type t = ((ArrayType) stack().peek(1)).getBasicType();
+        final Type t = ((ArrayType) stack().peek(1)).getElementType();
         if (t != Type.FLOAT) {
             constraintViolated(o, "Stack next-to-top must be of type float[] 
but is '" + stack().peek(1) + "'.");
         }
@@ -846,7 +846,7 @@ public class InstConstraintVisitor extends EmptyVisitor {
         if (!(stack().peek(2) instanceof ArrayType)) {
             constraintViolated(o, "Stack next-to-next-to-top must be of type 
float[] but is '" + stack().peek(2) + "'.");
         }
-        final Type t = ((ArrayType) stack().peek(2)).getBasicType();
+        final Type t = ((ArrayType) stack().peek(2)).getElementType();
         if (t != Type.FLOAT) {
             constraintViolated(o, "Stack next-to-next-to-top must be of type 
float[] but is '" + stack().peek(2) + "'.");
         }
@@ -1199,7 +1199,7 @@ public class InstConstraintVisitor extends EmptyVisitor {
         if (!(stack().peek(1) instanceof ArrayType)) {
             constraintViolated(o, "Stack next-to-top must be of type int[] but 
is '" + stack().peek(1) + "'.");
         }
-        final Type t = ((ArrayType) stack().peek(1)).getBasicType();
+        final Type t = ((ArrayType) stack().peek(1)).getElementType();
         if (t != Type.INT) {
             constraintViolated(o, "Stack next-to-top must be of type int[] but 
is '" + stack().peek(1) + "'.");
         }
@@ -1233,7 +1233,7 @@ public class InstConstraintVisitor extends EmptyVisitor {
         if (!(stack().peek(2) instanceof ArrayType)) {
             constraintViolated(o, "Stack next-to-next-to-top must be of type 
int[] but is '" + stack().peek(2) + "'.");
         }
-        final Type t = ((ArrayType) stack().peek(2)).getBasicType();
+        final Type t = ((ArrayType) stack().peek(2)).getElementType();
         if (t != Type.INT) {
             constraintViolated(o, "Stack next-to-next-to-top must be of type 
int[] but is '" + stack().peek(2) + "'.");
         }
@@ -1970,7 +1970,7 @@ public class InstConstraintVisitor extends EmptyVisitor {
         if (!(stack().peek(1) instanceof ArrayType)) {
             constraintViolated(o, "Stack next-to-top must be of type long[] 
but is '" + stack().peek(1) + "'.");
         }
-        final Type t = ((ArrayType) stack().peek(1)).getBasicType();
+        final Type t = ((ArrayType) stack().peek(1)).getElementType();
         if (t != Type.LONG) {
             constraintViolated(o, "Stack next-to-top must be of type long[] 
but is '" + stack().peek(1) + "'.");
         }
@@ -2004,7 +2004,7 @@ public class InstConstraintVisitor extends EmptyVisitor {
         if (!(stack().peek(2) instanceof ArrayType)) {
             constraintViolated(o, "Stack next-to-next-to-top must be of type 
long[] but is '" + stack().peek(2) + "'.");
         }
-        final Type t = ((ArrayType) stack().peek(2)).getBasicType();
+        final Type t = ((ArrayType) stack().peek(2)).getElementType();
         if (t != Type.LONG) {
             constraintViolated(o, "Stack next-to-next-to-top must be of type 
long[] but is '" + stack().peek(2) + "'.");
         }
@@ -2552,7 +2552,7 @@ public class InstConstraintVisitor extends EmptyVisitor {
         if (!(stack().peek(1) instanceof ArrayType)) {
             constraintViolated(o, "Stack next-to-top must be of type short[] 
but is '" + stack().peek(1) + "'.");
         }
-        final Type t = ((ArrayType) stack().peek(1)).getBasicType();
+        final Type t = ((ArrayType) stack().peek(1)).getElementType();
         if (t != Type.SHORT) {
             constraintViolated(o, "Stack next-to-top must be of type short[] 
but is '" + stack().peek(1) + "'.");
         }
@@ -2573,7 +2573,7 @@ public class InstConstraintVisitor extends EmptyVisitor {
         if (!(stack().peek(2) instanceof ArrayType)) {
             constraintViolated(o, "Stack next-to-next-to-top must be of type 
short[] but is '" + stack().peek(2) + "'.");
         }
-        final Type t = ((ArrayType) stack().peek(2)).getBasicType();
+        final Type t = ((ArrayType) stack().peek(2)).getElementType();
         if (t != Type.SHORT) {
             constraintViolated(o, "Stack next-to-next-to-top must be of type 
short[] but is '" + stack().peek(2) + "'.");
         }
diff --git 
a/src/test/java/org/apache/bcel/verifier/VerifierArrayAccessTest.java 
b/src/test/java/org/apache/bcel/verifier/VerifierArrayAccessTest.java
index d44bc9d9..3f96b04e 100644
--- a/src/test/java/org/apache/bcel/verifier/VerifierArrayAccessTest.java
+++ b/src/test/java/org/apache/bcel/verifier/VerifierArrayAccessTest.java
@@ -31,6 +31,7 @@ import 
org.apache.bcel.verifier.tests.TestArrayAccess04IntCreator;
 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.junit.jupiter.api.Test;
 
 class VerifierArrayAccessTest extends AbstractVerifierTest {
@@ -51,6 +52,8 @@ class VerifierArrayAccessTest extends AbstractVerifierTest {
         assertVerifyRejected("TestArrayAccess04Short", "Verification of an 
arraystore instruction of a short on an array of references must fail.");
         final TestArrayAccess04UnknownCreator testArrayAccess04UnknownCreator 
= new TestArrayAccess04UnknownCreator();
         assertThrowsExactly(IllegalArgumentException.class, 
testArrayAccess04UnknownCreator::create, "Invalid type <unknown object>");
+        new TestArrayAccess05Creator().create();
+        assertVerifyRejected("TestArrayAccess05", "Verification of iaload 
applied to a multidimensional int[][] must fail.");
     }
 
     @Test
diff --git 
a/src/test/java/org/apache/bcel/verifier/tests/TestArrayAccess05Creator.java 
b/src/test/java/org/apache/bcel/verifier/tests/TestArrayAccess05Creator.java
new file mode 100644
index 00000000..bd01b83f
--- /dev/null
+++ b/src/test/java/org/apache/bcel/verifier/tests/TestArrayAccess05Creator.java
@@ -0,0 +1,92 @@
+/*
+ * 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 iaload} directly to an {@code int[][]} 
reference, that is, without first indexing
+ * into the outer dimension. The component type of {@code int[][]} is {@code 
int[]} (a reference), so {@code iaload} is
+ * illegal and structural verification must reject it.
+ */
+public class TestArrayAccess05Creator extends TestCreator {
+    private final InstructionFactory factory;
+    private final ConstantPoolGen cp;
+    private final ClassGen cg;
+
+    public TestArrayAccess05Creator() {
+        cg = new ClassGen(TEST_PACKAGE + ".TestArrayAccess05", 
"java.lang.Object", "TestArrayAccess05.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 + ".TestArrayAccess05", 
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 + ".TestArrayAccess05", il, cp);
+
+        il.append(new PUSH(cp, 1));
+        il.append(new PUSH(cp, 1));
+        il.append(factory.createNewArray(Type.INT, (short) 2)); // int[][]
+        il.append(new PUSH(cp, 0));
+        il.append(InstructionConst.IALOAD); // iaload 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