Skip to content

Commit

Permalink
BCEL-363 Enforce MAX_CP_ENTRIES in ConstantPoolGen and ConstantPool.d…
Browse files Browse the repository at this point in the history
…ump (#147)

* BCEL-363 Enforce MAX_CP_ENTRIES in ConstantPoolGen and ConstantPool.dump

* BCEL-363 Add test coverage for enforced size limit

* BCEL-363 Throw IllegalStateException instead of RuntimeException

* BCEL-363 Use final
  • Loading branch information
rjatkins authored Sep 21, 2022
1 parent 51406ff commit f3267cb
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 3 deletions.
11 changes: 9 additions & 2 deletions src/main/java/org/apache/bcel/classfile/ConstantPool.java
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand Down
11 changes: 10 additions & 1 deletion src/main/java/org/apache/bcel/generic/ConstantPoolGen.java
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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);
}
Expand Down
15 changes: 15 additions & 0 deletions src/test/java/org/apache/bcel/classfile/ConstantPoolTestCase.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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));
}
}

0 comments on commit f3267cb

Please sign in to comment.