Commit b8650d7c authored by Jason Zaugg's avatar Jason Zaugg

Improve error message when writing a class with an oversized constant pool

parent ae11250c
package org.objectweb.asm;
public final class ClassTooLargeException extends IndexOutOfBoundsException {
private final String className;
private final int constantPoolCount;
/**
* @return The name of the class, or <tt>null</tt> if not known
*/
public String getClassName() {
return className;
}
/**
* @return The number of byte codes in the method.
*/
public int getConstantPoolCount() {
return constantPoolCount;
}
public ClassTooLargeException(String className, int constantPoolCount) {
super("Class file too large" + (className == null ? "" : ": " + className));
this.className = className;
this.constantPoolCount = constantPoolCount;
}
}
......@@ -543,8 +543,9 @@ public class ClassWriter extends ClassVisitor {
// IMPORTANT: this must be the last part of the ClassFile size computation, because the previous
// statements can add attribute names to the constant pool, thereby changing its size!
size += symbolTable.getConstantPoolLength();
if (symbolTable.getConstantPoolCount() > 0xFFFF) {
throw new IndexOutOfBoundsException("Class file too large!");
int constantPoolCount = symbolTable.getConstantPoolCount();
if (constantPoolCount > 0xFFFF) {
throw new ClassTooLargeException(symbolTable.getClassName(), constantPoolCount);
}
// Second step: allocate a ByteVector of the correct size (in order to avoid any array copy in
......
......@@ -28,8 +28,7 @@
package org.objectweb.asm;
import static java.util.stream.Collectors.toSet;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.*;
import static org.objectweb.asm.test.Assertions.assertThat;
import java.io.FileInputStream;
......@@ -129,11 +128,18 @@ public class ClassWriterTest extends AsmTest {
@ValueSource(ints = {65535, 65536})
public void testConstantPoolSizeTooLarge(final int constantPoolCount) {
ClassWriter classWriter = new ClassWriter(0);
for (int i = 0; i < constantPoolCount - 1; ++i) {
String className = "A";
classWriter.visit(Opcodes.V1_7, Opcodes.ACC_PUBLIC, className, null, "java/lang/Object", null);
int initConstantPoolCount = 5;
// assert(initConstantPoolCount == classWriter.symbolTable.getConstantPoolCount())
for (int i = 0; i < constantPoolCount - initConstantPoolCount; ++i) {
classWriter.newConst(Integer.valueOf(i));
}
if (constantPoolCount > 65535) {
assertThrows(IndexOutOfBoundsException.class, () -> classWriter.toByteArray());
ClassTooLargeException thrown = assertThrows(ClassTooLargeException.class, () -> classWriter.toByteArray());
assertEquals(className, thrown.getClassName());
assertEquals(constantPoolCount, thrown.getConstantPoolCount());
assertEquals("Class file too large: A", thrown.getMessage());
} else {
classWriter.toByteArray();
}
......@@ -157,7 +163,7 @@ public class ClassWriterTest extends AsmTest {
if (methodCodeSize > 65535) {
MethodTooLargeException thrown = assertThrows(MethodTooLargeException.class, () -> classWriter.toByteArray());
assertEquals(methodName, thrown.getMethodName());
assertEquals(null, thrown.getClassName());
assertNull(thrown.getClassName());
assertEquals(descriptor, thrown.getDescriptor());
assertEquals(methodCodeSize, thrown.getCodeSize());
assertEquals("Method code too large: m ()V", thrown.getMessage());
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment