diff --git a/spring-core/src/main/java/org/springframework/asm/AnnotationVisitor.java b/spring-core/src/main/java/org/springframework/asm/AnnotationVisitor.java index 6294ecebe24..83312531e8c 100644 --- a/spring-core/src/main/java/org/springframework/asm/AnnotationVisitor.java +++ b/spring-core/src/main/java/org/springframework/asm/AnnotationVisitor.java @@ -129,9 +129,9 @@ public abstract class AnnotationVisitor { } /** - * Visits an array value of the annotation. Note that arrays of primitive types (such as byte, + * Visits an array value of the annotation. Note that arrays of primitive values (such as byte, * boolean, short, char, int, long, float or double) can be passed as value to {@link #visit - * visit}. This is what {@link ClassReader} does. + * visit}. This is what {@link ClassReader} does for non empty arrays of primitive values. * * @param name the value name. * @return a visitor to visit the actual array value elements, or {@literal null} if this visitor diff --git a/spring-core/src/main/java/org/springframework/asm/ClassReader.java b/spring-core/src/main/java/org/springframework/asm/ClassReader.java index 308f5048103..62d00229f60 100644 --- a/spring-core/src/main/java/org/springframework/asm/ClassReader.java +++ b/spring-core/src/main/java/org/springframework/asm/ClassReader.java @@ -100,8 +100,10 @@ public class ClassReader { @Deprecated // DontCheck(MemberName): can't be renamed (for backward binary compatibility). public final byte[] b; + /** The offset in bytes of the ClassFile's access_flags field. */ public final int header; + /** * A byte array containing the JVMS ClassFile structure to be parsed. The content of this array * must not be modified. This field is intended for {@link Attribute} sub classes, and is normally @@ -112,6 +114,7 @@ public class ClassReader { * ClassFile element offsets within this byte array. */ final byte[] classFileBuffer; + /** * The offset in bytes, in {@link #classFileBuffer}, of each cp_info entry of the ClassFile's * constant_pool array, plus one. In other words, the offset of constant pool entry i is @@ -119,16 +122,19 @@ public class ClassReader { * 1]. */ private final int[] cpInfoOffsets; + /** * The String objects corresponding to the CONSTANT_Utf8 constant pool items. This cache avoids * multiple parsing of a given CONSTANT_Utf8 constant pool item. */ private final String[] constantUtf8Values; + /** * The ConstantDynamic objects corresponding to the CONSTANT_Dynamic constant pool items. This * cache avoids multiple parsing of a given CONSTANT_Dynamic constant pool item. */ private final ConstantDynamic[] constantDynamicValues; + /** * The start offsets in {@link #classFileBuffer} of each element of the bootstrap_methods array * (in the BootstrapMethods attribute). @@ -137,6 +143,7 @@ public class ClassReader { * 4.7.23 */ private final int[] bootstrapMethodOffsets; + /** * A conservative estimate of the maximum length of the strings contained in the constant pool of * the class. @@ -184,7 +191,7 @@ public class ClassReader { this.b = classFileBuffer; // Check the class' major_version. This field is after the magic and minor_version fields, which // use 4 and 2 bytes respectively. - if (checkClassVersion && readShort(classFileOffset + 6) > Opcodes.V16) { + if (checkClassVersion && readShort(classFileOffset + 6) > Opcodes.V17) { throw new IllegalArgumentException( "Unsupported class file major version " + readShort(classFileOffset + 6)); } @@ -499,6 +506,9 @@ public class ClassReader { } else if (Constants.SYNTHETIC.equals(attributeName)) { accessFlags |= Opcodes.ACC_SYNTHETIC; } else if (Constants.SOURCE_DEBUG_EXTENSION.equals(attributeName)) { + if (attributeLength > classFileBuffer.length - currentAttributeOffset) { + throw new IllegalArgumentException(); + } sourceDebugExtension = readUtf(currentAttributeOffset, attributeLength, new char[attributeLength]); } else if (Constants.RUNTIME_INVISIBLE_ANNOTATIONS.equals(attributeName)) { @@ -1509,6 +1519,9 @@ public class ClassReader { final int maxLocals = readUnsignedShort(currentOffset + 2); final int codeLength = readInt(currentOffset + 4); currentOffset += 8; + if (codeLength > classFileBuffer.length - currentOffset) { + throw new IllegalArgumentException(); + } // Read the bytecode 'code' array to create a label for each referenced instruction. final int bytecodeStartOffset = currentOffset; @@ -2965,7 +2978,7 @@ public class ClassReader { // Parse the array_value array. while (numElementValuePairs-- > 0) { currentOffset = - readElementValue(annotationVisitor, currentOffset, /* elementName = */ null, charBuffer); + readElementValue(annotationVisitor, currentOffset, /* elementName= */ null, charBuffer); } } if (annotationVisitor != null) { diff --git a/spring-core/src/main/java/org/springframework/asm/Opcodes.java b/spring-core/src/main/java/org/springframework/asm/Opcodes.java index 52e35ddc391..f9cc14315bb 100644 --- a/spring-core/src/main/java/org/springframework/asm/Opcodes.java +++ b/spring-core/src/main/java/org/springframework/asm/Opcodes.java @@ -132,7 +132,7 @@ public interface Opcodes { *
    * public class StuffVisitor {
    *   @Deprecated public void visitOldStuff(int arg, ...) {
-   *     visitNewStuf(arg | SOURCE_DEPRECATED, ...);
+   *     visitNewStuff(arg | SOURCE_DEPRECATED, ...);
    *   }
    *   public void visitNewStuff(int argAndSource...) {
    *     if ((argAndSource & SOURCE_DEPRECATED) == 0) {
@@ -154,7 +154,7 @@ public interface Opcodes {
    * 

and there are two cases: * *