Commit ae11250c authored by Jason Zaugg's avatar Jason Zaugg
Browse files

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 { ...@@ -305,6 +305,9 @@ final class MethodWriter extends MethodVisitor {
/** The descriptor of this method. */ /** The descriptor of this method. */
private final String descriptor; private final String descriptor;
/** The name of this method. */
private final String name;
// Code attribute fields and sub attributes: // Code attribute fields and sub attributes:
/** The max_stack field of the Code attribute. */ /** The max_stack field of the Code attribute. */
...@@ -592,6 +595,7 @@ final class MethodWriter extends MethodVisitor { ...@@ -592,6 +595,7 @@ final class MethodWriter extends MethodVisitor {
this.symbolTable = symbolTable; this.symbolTable = symbolTable;
this.accessFlags = "<init>".equals(name) ? access | Constants.ACC_CONSTRUCTOR : access; this.accessFlags = "<init>".equals(name) ? access | Constants.ACC_CONSTRUCTOR : access;
this.nameIndex = symbolTable.addConstantUtf8(name); this.nameIndex = symbolTable.addConstantUtf8(name);
this.name = name;
this.descriptorIndex = symbolTable.addConstantUtf8(descriptor); this.descriptorIndex = symbolTable.addConstantUtf8(descriptor);
this.descriptor = descriptor; this.descriptor = descriptor;
this.signatureIndex = signature == null ? 0 : symbolTable.addConstantUtf8(signature); this.signatureIndex = signature == null ? 0 : symbolTable.addConstantUtf8(signature);
...@@ -2058,7 +2062,7 @@ final class MethodWriter extends MethodVisitor { ...@@ -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. // 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 > 0) {
if (code.length > 65535) { if (code.length > 65535) {
throw new IndexOutOfBoundsException("Method code too large!"); throw new MethodTooLargeException(symbolTable.getClassName(), name, descriptor, code.length);
} }
symbolTable.addConstantUtf8(Constants.CODE); symbolTable.addConstantUtf8(Constants.CODE);
// The Code attribute has 6 header bytes, plus 2, 2, 4 and 2 bytes respectively for max_stack, // 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 { ...@@ -143,8 +143,10 @@ public class ClassWriterTest extends AsmTest {
@ValueSource(ints = {65535, 65536}) @ValueSource(ints = {65535, 65536})
void testMethodCodeSizeTooLarge(final int methodCodeSize) { void testMethodCodeSizeTooLarge(final int methodCodeSize) {
ClassWriter classWriter = new ClassWriter(0); ClassWriter classWriter = new ClassWriter(0);
String methodName = "m";
String descriptor = "()V";
MethodVisitor methodVisitor = MethodVisitor methodVisitor =
classWriter.visitMethod(Opcodes.ACC_STATIC, "m", "()V", null, null); classWriter.visitMethod(Opcodes.ACC_STATIC, methodName, descriptor, null, null);
methodVisitor.visitCode(); methodVisitor.visitCode();
for (int i = 0; i < methodCodeSize - 1; ++i) { for (int i = 0; i < methodCodeSize - 1; ++i) {
methodVisitor.visitInsn(Opcodes.NOP); methodVisitor.visitInsn(Opcodes.NOP);
...@@ -153,7 +155,12 @@ public class ClassWriterTest extends AsmTest { ...@@ -153,7 +155,12 @@ public class ClassWriterTest extends AsmTest {
methodVisitor.visitMaxs(0, 0); methodVisitor.visitMaxs(0, 0);
methodVisitor.visitEnd(); methodVisitor.visitEnd();
if (methodCodeSize > 65535) { 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 { } else {
classWriter.toByteArray(); 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