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 8f9a414b Validate index upper bound in CPInstruction, IINC and RET 
setIndex (#506)
8f9a414b is described below

commit 8f9a414b118fbe39fb3a476d78afd89d41990da1
Author: Dexter.k <[email protected]>
AuthorDate: Sat Jun 20 15:22:09 2026 +0000

    Validate index upper bound in CPInstruction, IINC and RET setIndex (#506)
    
    * validate index upper bound in CPInstruction, IINC and RET setIndex
    
    these setters only rejected negative indices, so an index above 
Const.MAX_SHORT was silently truncated to a u2 by dump(); match 
LocalVariableInstruction.setIndex which already guards both bounds.
    
    * No need for a FQCN, use an import like everywhere else.
    
    * Update CPInstruction.java
    
    * Update CPInstruction.java
    
    ---------
    
    Co-authored-by: Gary Gregory <[email protected]>
---
 .../org/apache/bcel/generic/CPInstruction.java     |  9 ++--
 src/main/java/org/apache/bcel/generic/IINC.java    |  4 +-
 src/main/java/org/apache/bcel/generic/RET.java     |  4 +-
 .../apache/bcel/generic/SetIndexBoundsTest.java    | 53 ++++++++++++++++++++++
 4 files changed, 62 insertions(+), 8 deletions(-)

diff --git a/src/main/java/org/apache/bcel/generic/CPInstruction.java 
b/src/main/java/org/apache/bcel/generic/CPInstruction.java
index d0a54c8f..8737c27a 100644
--- a/src/main/java/org/apache/bcel/generic/CPInstruction.java
+++ b/src/main/java/org/apache/bcel/generic/CPInstruction.java
@@ -21,6 +21,7 @@ package org.apache.bcel.generic;
 import java.io.DataOutputStream;
 import java.io.IOException;
 
+import org.apache.bcel.Const;
 import org.apache.bcel.classfile.Constant;
 import org.apache.bcel.classfile.ConstantClass;
 import org.apache.bcel.classfile.ConstantPool;
@@ -84,7 +85,7 @@ public abstract class CPInstruction extends Instruction 
implements TypedInstruct
     @Override
     public Type getType(final ConstantPoolGen cpg) {
         final ConstantPool cp = cpg.getConstantPool();
-        String name = cp.getConstantString(index, 
org.apache.bcel.Const.CONSTANT_Class);
+        String name = cp.getConstantString(index, Const.CONSTANT_Class);
         if (!name.startsWith("[")) {
             name = "L" + name + ";";
         }
@@ -110,8 +111,8 @@ public abstract class CPInstruction extends Instruction 
implements TypedInstruct
      */
     @Override
     public void setIndex(final int index) { // TODO could be package-protected?
-        if (index < 0) {
-            throw new ClassGenException("Negative index value: " + index);
+        if (index < 0 || index > Const.MAX_SHORT) {
+            throw new ClassGenException("Illegal value: " + index);
         }
         this.index = index;
     }
@@ -140,6 +141,6 @@ public abstract class CPInstruction extends Instruction 
implements TypedInstruct
         if (c instanceof ConstantClass) {
             str = Utility.packageToPath(str);
         }
-        return org.apache.bcel.Const.getOpcodeName(super.getOpcode()) + " " + 
str;
+        return Const.getOpcodeName(super.getOpcode()) + " " + str;
     }
 }
diff --git a/src/main/java/org/apache/bcel/generic/IINC.java 
b/src/main/java/org/apache/bcel/generic/IINC.java
index 37799fd5..45b479e6 100644
--- a/src/main/java/org/apache/bcel/generic/IINC.java
+++ b/src/main/java/org/apache/bcel/generic/IINC.java
@@ -135,8 +135,8 @@ public class IINC extends LocalVariableInstruction {
      */
     @Override
     public final void setIndex(final int n) {
-        if (n < 0) {
-            throw new ClassGenException("Negative index value: " + n);
+        if (n < 0 || n > Const.MAX_SHORT) {
+            throw new ClassGenException("Illegal value: " + n);
         }
         super.setIndexOnly(n);
         setWide();
diff --git a/src/main/java/org/apache/bcel/generic/RET.java 
b/src/main/java/org/apache/bcel/generic/RET.java
index 25c7a9f4..0bf22f16 100644
--- a/src/main/java/org/apache/bcel/generic/RET.java
+++ b/src/main/java/org/apache/bcel/generic/RET.java
@@ -116,8 +116,8 @@ public class RET extends Instruction implements 
IndexedInstruction, TypedInstruc
      */
     @Override
     public final void setIndex(final int n) {
-        if (n < 0) {
-            throw new ClassGenException("Negative index value: " + n);
+        if (n < 0 || n > org.apache.bcel.Const.MAX_SHORT) {
+            throw new ClassGenException("Illegal value: " + n);
         }
         index = n;
         setWide();
diff --git a/src/test/java/org/apache/bcel/generic/SetIndexBoundsTest.java 
b/src/test/java/org/apache/bcel/generic/SetIndexBoundsTest.java
new file mode 100644
index 00000000..888710c0
--- /dev/null
+++ b/src/test/java/org/apache/bcel/generic/SetIndexBoundsTest.java
@@ -0,0 +1,53 @@
+/*
+ * 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.generic;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+
+import org.apache.bcel.Const;
+import org.junit.jupiter.api.Test;
+
+/**
+ * A constant pool or local variable index is encoded as a u2, so {@code 
setIndex} must reject a value above
+ * {@link Const#MAX_SHORT}; otherwise {@code dump} truncates it with {@code 
writeShort} and the emitted instruction
+ * references a different slot than requested. {@code 
LocalVariableInstruction.setIndex} already enforces this; these
+ * cover the siblings that did not.
+ */
+class SetIndexBoundsTest {
+
+    @Test
+    void testCpInstructionRejectsIndexAboveU2() {
+        assertEquals(Const.MAX_SHORT, new LDC_W(Const.MAX_SHORT).getIndex());
+        assertThrows(ClassGenException.class, () -> new LDC_W(Const.MAX_SHORT 
+ 1));
+    }
+
+    @Test
+    void testIincRejectsIndexAboveU2() {
+        assertEquals(Const.MAX_SHORT, new IINC(Const.MAX_SHORT, 1).getIndex());
+        assertThrows(ClassGenException.class, () -> new IINC(Const.MAX_SHORT + 
1, 1));
+    }
+
+    @Test
+    void testRetRejectsIndexAboveU2() {
+        assertEquals(Const.MAX_SHORT, new RET(Const.MAX_SHORT).getIndex());
+        assertThrows(ClassGenException.class, () -> new RET(Const.MAX_SHORT + 
1));
+    }
+}

Reply via email to