Commit 94a06049 authored by Jason Zaugg's avatar Jason Zaugg

Improve the message for a too-long UTF-8 constant

parent e9c5bf36
......@@ -242,7 +242,7 @@ public class ByteVector {
public ByteVector putUTF8(final String stringValue) {
int charLength = stringValue.length();
if (charLength > 65535) {
throw new IllegalArgumentException();
throw new IllegalArgumentException("Maximum size for a UTF-8 string constant exceeded");
}
int currentLength = length;
if (currentLength + 2 + charLength > data.length) {
......
......@@ -28,26 +28,22 @@
package org.objectweb.asm;
public final class ClassTooLargeException extends IndexOutOfBoundsException {
private final String className;
private final int constantPoolCount;
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 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;
}
/** @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;
}
public ClassTooLargeException(String className, int constantPoolCount) {
super("Class file too large" + (className == null ? "" : ": " + className));
this.className = className;
this.constantPoolCount = constantPoolCount;
}
}
......@@ -28,44 +28,42 @@
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;
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 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 name of the method */
public String getMethodName() {
return methodName;
}
/**
* @return The descriptor of the the method
*/
public String getDescriptor() {
return descriptor;
}
/** @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;
}
/** @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;
}
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;
}
}
......@@ -2062,7 +2062,8 @@ 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 MethodTooLargeException(symbolTable.getClassName(), name, descriptor, code.length);
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,
......
......@@ -31,7 +31,10 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
import java.util.Arrays;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource;
/**
* ByteVector tests.
......@@ -113,12 +116,26 @@ public class ByteVectorTest {
assertContains(byteVector, 0, 8, 'a', -64, -128, -62, -128, -32, -96, -128);
char[] charBuffer = new char[32768];
for (int i = 0; i < charBuffer.length; ++i) {
charBuffer[i] = '\u07FF';
}
Arrays.fill(charBuffer, '\u07FF');
assertThrows(IllegalArgumentException.class, () -> byteVector.putUTF8(new String(charBuffer)));
}
@ParameterizedTest
@ValueSource(ints = {65535, 65536})
public void testPutUTF8_tooLong(int size) {
ByteVector byteVector = new ByteVector(0);
char[] charBuffer = new char[size];
Arrays.fill(charBuffer, 'A');
String s = new String(charBuffer);
if (size > 65535) {
IllegalArgumentException thrown =
assertThrows(IllegalArgumentException.class, () -> byteVector.putUTF8(s));
assertEquals("Maximum size for a UTF-8 string constant exceeded", thrown.getMessage());
} else {
byteVector.putUTF8(s);
}
}
@Test
public void testPutByteArray() {
ByteVector byteVector = new ByteVector(0);
......
......@@ -136,7 +136,8 @@ public class ClassWriterTest extends AsmTest {
classWriter.newConst(Integer.valueOf(i));
}
if (constantPoolCount > 65535) {
ClassTooLargeException thrown = assertThrows(ClassTooLargeException.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());
......@@ -161,7 +162,8 @@ public class ClassWriterTest extends AsmTest {
methodVisitor.visitMaxs(0, 0);
methodVisitor.visitEnd();
if (methodCodeSize > 65535) {
MethodTooLargeException thrown = assertThrows(MethodTooLargeException.class, () -> classWriter.toByteArray());
MethodTooLargeException thrown =
assertThrows(MethodTooLargeException.class, () -> classWriter.toByteArray());
assertEquals(methodName, thrown.getMethodName());
assertNull(thrown.getClassName());
assertEquals(descriptor, thrown.getDescriptor());
......
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