diff --git a/src/main/java/org/apache/bcel/classfile/ConstantPool.java b/src/main/java/org/apache/bcel/classfile/ConstantPool.java index 0a9ab79afd..8e8fddf709 100644 --- a/src/main/java/org/apache/bcel/classfile/ConstantPool.java +++ b/src/main/java/org/apache/bcel/classfile/ConstantPool.java @@ -230,8 +230,15 @@ public ConstantPool copy() { * @throws IOException if problem in writeShort or dump */ public void dump(final DataOutputStream file) throws IOException { - file.writeShort(constantPool.length); - for (int i = 1; i < constantPool.length; i++) { + /* + * Constants over the size of the constant pool shall not be written out. + * This is a redundant measure as the ConstantPoolGen should have already + * reported an error back in the situation. + */ + final int size = Math.min(constantPool.length, Const.MAX_CP_ENTRIES); + + file.writeShort(size); + for (int i = 1; i < size; i++) { if (constantPool[i] != null) { constantPool[i].dump(file); } diff --git a/src/main/java/org/apache/bcel/generic/ConstantPoolGen.java b/src/main/java/org/apache/bcel/generic/ConstantPoolGen.java index 3d91b41614..d55f321885 100644 --- a/src/main/java/org/apache/bcel/generic/ConstantPoolGen.java +++ b/src/main/java/org/apache/bcel/generic/ConstantPoolGen.java @@ -109,7 +109,7 @@ public ConstantPoolGen() { public ConstantPoolGen(final Constant[] cs) { final StringBuilder sb = new StringBuilder(DEFAULT_BUFFER_SIZE); - size = Math.max(DEFAULT_BUFFER_SIZE, cs.length + 64); + size = Math.min(Math.max(DEFAULT_BUFFER_SIZE, cs.length + 64), Const.MAX_CP_ENTRIES + 1); constants = new Constant[size]; System.arraycopy(cs, 0, constants, 0, cs.length); @@ -561,9 +561,18 @@ public int addUtf8(final String n) { * Resize internal array of constants. */ protected void adjustSize() { + // 3 extra spaces are needed as some entries may take 3 slots + if (index + 3 >= Const.MAX_CP_ENTRIES + 1) { + throw new IllegalStateException("The number of constants " + (index + 3) + + " is over the size of the constant pool: " + + Const.MAX_CP_ENTRIES); + } + if (index + 3 >= size) { final Constant[] cs = constants; size *= 2; + // the constant array shall not exceed the size of the constant pool + size = Math.min(size, Const.MAX_CP_ENTRIES + 1); constants = new Constant[size]; System.arraycopy(cs, 0, constants, 0, index); } diff --git a/src/test/java/org/apache/bcel/classfile/ConstantPoolTestCase.java b/src/test/java/org/apache/bcel/classfile/ConstantPoolTestCase.java index fae5bcf78c..5e47998328 100644 --- a/src/test/java/org/apache/bcel/classfile/ConstantPoolTestCase.java +++ b/src/test/java/org/apache/bcel/classfile/ConstantPoolTestCase.java @@ -18,8 +18,10 @@ package org.apache.bcel.classfile; import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertThrows; import org.apache.bcel.AbstractTestCase; +import org.apache.bcel.Const; import org.apache.bcel.generic.ConstantPoolGen; import org.apache.bcel.generic.InstructionHandle; import org.apache.bcel.generic.InstructionList; @@ -52,4 +54,17 @@ public void testConstantToString() throws ClassNotFoundException { } } } + + @Test + public void testTooManyConstants() throws ClassNotFoundException { + final JavaClass clazz = getTestClass(PACKAGE_BASE_NAME + ".data.SimpleClassWithDefaultConstructor"); + final ConstantPoolGen cp = new ConstantPoolGen(clazz.getConstantPool()); + + int i = cp.getSize(); + while (i < Const.MAX_CP_ENTRIES - 1) { + cp.addLong(i); + i = cp.getSize(); // i += 2 + } + assertThrows(IllegalStateException.class, () -> cp.addLong(0)); + } }