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();
+ }
+}