Commit ae11250c authored by Jason Zaugg's avatar Jason Zaugg

Improve the error when a method is too large

parent c4a9e49c
package org.objectweb.asm;
public final class MethodTooLargeException extends IndexOutOfBoundsException {
private final String className;
private final String methodName;
private final String descriptor;
private final int codeSize;
/**
* @return The name of the enclosing class, or <tt>null</tt> if not known
*/
public String getClassName() {
return className;
}
/**
* @return The name of the method
*/
public String getMethodName() {
return methodName;
}
/**
* @return The descriptor of the the method
*/
public String getDescriptor() {
return descriptor;
}
/**
* @return The number of byte codes in the method.
*/
public int getCodeSize() {
return codeSize;
}
public MethodTooLargeException(String className, String methodName, String descriptor, int codeSize) {
super("Method code too large: " + (className == null ? "" : className + ".") + methodName + " " + descriptor);
this.className = className;
this.methodName = methodName;
this.descriptor = descriptor;
this.codeSize = codeSize;
}
}
......@@ -305,6 +305,9 @@ final class MethodWriter extends MethodVisitor {
/** The descriptor of this method. */
private final String descriptor;
/** The name of this method. */
private final String name;
// Code attribute fields and sub attributes:
/** The max_stack field of the Code attribute. */
......@@ -592,6 +595,7 @@ final class MethodWriter extends MethodVisitor {
this.symbolTable = symbolTable;
this.accessFlags = "<init>".equals(name) ? access | Constants.ACC_CONSTRUCTOR : access;
this.nameIndex = symbolTable.addConstantUtf8(name);
this.name = name;
this.descriptorIndex = symbolTable.addConstantUtf8(descriptor);
this.descriptor = descriptor;
this.signatureIndex = signature == null ? 0 : symbolTable.addConstantUtf8(signature);
......@@ -2058,7 +2062,7 @@ final class MethodWriter extends MethodVisitor {
// For ease of reference, we use here the same attribute order as in Section 4.7 of the JVMS.
if (code.length > 0) {
if (code.length > 65535) {
throw new IndexOutOfBoundsException("Method code too large!");
throw new MethodTooLargeException(symbolTable.getClassName(), name, descriptor, code.length);
}
symbolTable.addConstantUtf8(Constants.CODE);
// The Code attribute has 6 header bytes, plus 2, 2, 4 and 2 bytes respectively for max_stack,
......
......@@ -143,8 +143,10 @@ public class ClassWriterTest extends AsmTest {
@ValueSource(ints = {65535, 65536})
void testMethodCodeSizeTooLarge(final int methodCodeSize) {
ClassWriter classWriter = new ClassWriter(0);
String methodName = "m";
String descriptor = "()V";
MethodVisitor methodVisitor =
classWriter.visitMethod(Opcodes.ACC_STATIC, "m", "()V", null, null);
classWriter.visitMethod(Opcodes.ACC_STATIC, methodName, descriptor, null, null);
methodVisitor.visitCode();
for (int i = 0; i < methodCodeSize - 1; ++i) {
methodVisitor.visitInsn(Opcodes.NOP);
......@@ -153,7 +155,12 @@ public class ClassWriterTest extends AsmTest {
methodVisitor.visitMaxs(0, 0);
methodVisitor.visitEnd();
if (methodCodeSize > 65535) {
assertThrows(IndexOutOfBoundsException.class, () -> classWriter.toByteArray());
MethodTooLargeException thrown = assertThrows(MethodTooLargeException.class, () -> classWriter.toByteArray());
assertEquals(methodName, thrown.getMethodName());
assertEquals(null, thrown.getClassName());
assertEquals(descriptor, thrown.getDescriptor());
assertEquals(methodCodeSize, thrown.getCodeSize());
assertEquals("Method code too large: m ()V", thrown.getMessage());
} else {
classWriter.toByteArray();
}
......
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