mirror of
https://github.com/openjdk/jdk.git
synced 2026-01-28 12:09:14 +00:00
8361635: Missing List length validation in the Class-File API
Reviewed-by: asotona
This commit is contained in:
parent
8d236615b7
commit
431f467246
@ -95,6 +95,8 @@ public sealed interface Annotation
|
||||
* @param annotationClass the constant pool entry holding the descriptor string
|
||||
* of the annotation interface
|
||||
* @param elements the element-value pairs of the annotation
|
||||
* @throws IllegalArgumentException if the number of pairs exceeds the limit
|
||||
* of {@link java.lang.classfile##u2 u2}
|
||||
*/
|
||||
static Annotation of(Utf8Entry annotationClass,
|
||||
List<AnnotationElement> elements) {
|
||||
@ -106,6 +108,8 @@ public sealed interface Annotation
|
||||
* @param annotationClass the constant pool entry holding the descriptor string
|
||||
* of the annotation interface
|
||||
* @param elements the element-value pairs of the annotation
|
||||
* @throws IllegalArgumentException if the number of pairs exceeds the limit
|
||||
* of {@link java.lang.classfile##u2 u2}
|
||||
*/
|
||||
static Annotation of(Utf8Entry annotationClass,
|
||||
AnnotationElement... elements) {
|
||||
@ -116,6 +120,8 @@ public sealed interface Annotation
|
||||
* {@return an annotation}
|
||||
* @param annotationClass the descriptor of the annotation interface
|
||||
* @param elements the element-value pairs of the annotation
|
||||
* @throws IllegalArgumentException if the number of pairs exceeds the limit
|
||||
* of {@link java.lang.classfile##u2 u2}
|
||||
*/
|
||||
static Annotation of(ClassDesc annotationClass,
|
||||
List<AnnotationElement> elements) {
|
||||
@ -126,6 +132,8 @@ public sealed interface Annotation
|
||||
* {@return an annotation}
|
||||
* @param annotationClass the descriptor of the annotation interface
|
||||
* @param elements the element-value pairs of the annotation
|
||||
* @throws IllegalArgumentException if the number of pairs exceeds the limit
|
||||
* of {@link java.lang.classfile##u2 u2}
|
||||
*/
|
||||
static Annotation of(ClassDesc annotationClass,
|
||||
AnnotationElement... elements) {
|
||||
|
||||
@ -209,6 +209,8 @@ public sealed interface AnnotationElement
|
||||
* @param name the name of the key
|
||||
* @param values the associated values
|
||||
* @see AnnotationValue#ofArray(AnnotationValue...) AnnotationValue::ofArray
|
||||
* @throws IllegalArgumentException if the number of associated values
|
||||
* exceeds the limit of {@link java.lang.classfile##u2 u2}
|
||||
*/
|
||||
static AnnotationElement ofArray(String name,
|
||||
AnnotationValue... values) {
|
||||
|
||||
@ -673,6 +673,8 @@ public sealed interface AnnotationValue {
|
||||
* on array values derived from Java source code.
|
||||
*
|
||||
* @param values the array elements
|
||||
* @throws IllegalArgumentException if the length of array exceeds the limit
|
||||
* of {@link java.lang.classfile##u2 u2}
|
||||
*/
|
||||
static OfArray ofArray(List<AnnotationValue> values) {
|
||||
return new AnnotationImpl.OfArrayImpl(values);
|
||||
@ -686,6 +688,8 @@ public sealed interface AnnotationValue {
|
||||
* on array values derived from Java source code.
|
||||
*
|
||||
* @param values the array elements
|
||||
* @throws IllegalArgumentException if the length of array exceeds the limit
|
||||
* of {@link java.lang.classfile##u2 u2}
|
||||
*/
|
||||
static OfArray ofArray(AnnotationValue... values) {
|
||||
return ofArray(List.of(values));
|
||||
@ -699,7 +703,8 @@ public sealed interface AnnotationValue {
|
||||
* @param value the annotation value
|
||||
* @throws IllegalArgumentException when the {@code value} parameter is not
|
||||
* a primitive, a wrapper of primitive, a String, a ClassDesc,
|
||||
* an enum constant, or an array of one of these.
|
||||
* an enum constant, or an array of one of these; or any array has
|
||||
* length over the limit of {@link java.lang.classfile##u2 u2}
|
||||
*/
|
||||
static AnnotationValue of(Object value) {
|
||||
if (value instanceof String s) {
|
||||
|
||||
@ -131,6 +131,8 @@ public sealed interface ClassBuilder
|
||||
*
|
||||
* @param interfaces the interfaces
|
||||
* @return this builder
|
||||
* @throws IllegalArgumentException if the number of interfaces exceeds the
|
||||
* limit of {@link java.lang.classfile##u2 u2}
|
||||
* @see Interfaces
|
||||
*/
|
||||
default ClassBuilder withInterfaces(List<ClassEntry> interfaces) {
|
||||
@ -142,6 +144,8 @@ public sealed interface ClassBuilder
|
||||
*
|
||||
* @param interfaces the interfaces
|
||||
* @return this builder
|
||||
* @throws IllegalArgumentException if the number of interfaces exceeds the
|
||||
* limit of {@link java.lang.classfile##u2 u2}
|
||||
* @see Interfaces
|
||||
*/
|
||||
default ClassBuilder withInterfaces(ClassEntry... interfaces) {
|
||||
@ -153,7 +157,9 @@ public sealed interface ClassBuilder
|
||||
*
|
||||
* @param interfaces the interfaces
|
||||
* @return this builder
|
||||
* @throws IllegalArgumentException if any element of {@code interfaces} is primitive
|
||||
* @throws IllegalArgumentException if any of {@code interfaces} is primitive,
|
||||
* or if the number of interfaces exceeds the limit of {@link
|
||||
* java.lang.classfile##u2 u2}
|
||||
* @see Interfaces
|
||||
*/
|
||||
default ClassBuilder withInterfaceSymbols(List<ClassDesc> interfaces) {
|
||||
@ -165,7 +171,9 @@ public sealed interface ClassBuilder
|
||||
*
|
||||
* @param interfaces the interfaces
|
||||
* @return this builder
|
||||
* @throws IllegalArgumentException if any element of {@code interfaces} is primitive
|
||||
* @throws IllegalArgumentException if any of {@code interfaces} is primitive,
|
||||
* or if the number of interfaces exceeds the limit of {@link
|
||||
* java.lang.classfile##u2 u2}
|
||||
* @see Interfaces
|
||||
*/
|
||||
default ClassBuilder withInterfaceSymbols(ClassDesc... interfaces) {
|
||||
|
||||
@ -2402,8 +2402,8 @@ public sealed interface CodeBuilder
|
||||
* variable by a constant.
|
||||
* <p>
|
||||
* This may also generate {@link Opcode#IINC_W wide iinc} instructions if
|
||||
* {@code slot} exceeds {@code 255} or {@code val} exceeds the range of
|
||||
* {@link TypeKind#BYTE byte}.
|
||||
* {@code slot} exceeds the limit of {@link java.lang.classfile##u1 u1} or
|
||||
* {@code val} exceeds the range of {@link TypeKind#BYTE byte}.
|
||||
*
|
||||
* @param slot the local variable slot
|
||||
* @param val the increment value
|
||||
|
||||
@ -54,6 +54,8 @@ public sealed interface Interfaces
|
||||
/**
|
||||
* {@return an {@linkplain Interfaces} element}
|
||||
* @param interfaces the interfaces
|
||||
* @throws IllegalArgumentException if the number of interfaces
|
||||
* exceeds the limit of {@link java.lang.classfile##u2 u2}
|
||||
*/
|
||||
static Interfaces of(List<ClassEntry> interfaces) {
|
||||
return new InterfacesImpl(interfaces);
|
||||
@ -62,6 +64,8 @@ public sealed interface Interfaces
|
||||
/**
|
||||
* {@return an {@linkplain Interfaces} element}
|
||||
* @param interfaces the interfaces
|
||||
* @throws IllegalArgumentException if the number of interfaces
|
||||
* exceeds the limit of {@link java.lang.classfile##u2 u2}
|
||||
*/
|
||||
static Interfaces of(ClassEntry... interfaces) {
|
||||
return of(List.of(interfaces));
|
||||
@ -70,7 +74,9 @@ public sealed interface Interfaces
|
||||
/**
|
||||
* {@return an {@linkplain Interfaces} element}
|
||||
* @param interfaces the interfaces
|
||||
* @throws IllegalArgumentException if any of {@code interfaces} is primitive
|
||||
* @throws IllegalArgumentException if any of {@code interfaces} is primitive,
|
||||
* or if the number of interfaces exceeds the limit of {@link
|
||||
* java.lang.classfile##u2 u2}
|
||||
*/
|
||||
static Interfaces ofSymbols(List<ClassDesc> interfaces) {
|
||||
return of(Util.entryList(interfaces));
|
||||
@ -79,7 +85,9 @@ public sealed interface Interfaces
|
||||
/**
|
||||
* {@return an {@linkplain Interfaces} element}
|
||||
* @param interfaces the interfaces
|
||||
* @throws IllegalArgumentException if any of {@code interfaces} is primitive
|
||||
* @throws IllegalArgumentException if any of {@code interfaces} is primitive,
|
||||
* or if the number of interfaces exceeds the limit of {@link
|
||||
* java.lang.classfile##u2 u2}
|
||||
*/
|
||||
static Interfaces ofSymbols(ClassDesc... interfaces) {
|
||||
return ofSymbols(Arrays.asList(interfaces));
|
||||
|
||||
@ -182,6 +182,8 @@ public sealed interface TypeAnnotation
|
||||
* @param targetInfo which type in a declaration or expression is annotated
|
||||
* @param targetPath which part of the type is annotated
|
||||
* @param annotation the annotation
|
||||
* @throws IllegalArgumentException if the size of {@code targetPath}
|
||||
* exceeds the limit of {@link java.lang.classfile##u1 u1}
|
||||
*/
|
||||
static TypeAnnotation of(TargetInfo targetInfo, List<TypePathComponent> targetPath,
|
||||
Annotation annotation) {
|
||||
@ -486,6 +488,8 @@ public sealed interface TypeAnnotation
|
||||
* including a variable declared as a resource in a try-with-resources statement}
|
||||
* @param targetType {@link TargetType#LOCAL_VARIABLE} or {@link TargetType#RESOURCE_VARIABLE}
|
||||
* @param table the list of local variable targets
|
||||
* @throws IllegalArgumentException if the size of the list of targets
|
||||
* exceeds the limit of {@link java.lang.classfile##u2 u2}
|
||||
*/
|
||||
static LocalVarTarget ofVariable(TargetType targetType, List<LocalVarTargetInfo> table) {
|
||||
return new TargetInfoImpl.LocalVarTargetImpl(targetType, table);
|
||||
@ -494,6 +498,8 @@ public sealed interface TypeAnnotation
|
||||
/**
|
||||
* {@return a target for annotations on the type in a local variable declaration}
|
||||
* @param table the list of local variable targets
|
||||
* @throws IllegalArgumentException if the size of the list of targets
|
||||
* exceeds the limit of {@link java.lang.classfile##u2 u2}
|
||||
*/
|
||||
static LocalVarTarget ofLocalVariable(List<LocalVarTargetInfo> table) {
|
||||
return ofVariable(TargetType.LOCAL_VARIABLE, table);
|
||||
@ -503,6 +509,8 @@ public sealed interface TypeAnnotation
|
||||
* {@return a target for annotations on the type in a local variable declared
|
||||
* as a resource in a try-with-resources statement}
|
||||
* @param table the list of local variable targets
|
||||
* @throws IllegalArgumentException if the size of the list of targets
|
||||
* exceeds the limit of {@link java.lang.classfile##u2 u2}
|
||||
*/
|
||||
static LocalVarTarget ofResourceVariable(List<LocalVarTargetInfo> table) {
|
||||
return ofVariable(TargetType.RESOURCE_VARIABLE, table);
|
||||
@ -802,7 +810,6 @@ public sealed interface TypeAnnotation
|
||||
*/
|
||||
Label startLabel();
|
||||
|
||||
|
||||
/**
|
||||
* The given local variable has a value at indices into the code array in the interval
|
||||
* [start_pc, start_pc + length), that is, between start_pc inclusive and start_pc + length exclusive.
|
||||
|
||||
@ -88,6 +88,8 @@ public sealed interface CharacterRangeTableAttribute
|
||||
* {@link CodeBuilder#characterRange CodeBuilder::characterRange} instead.
|
||||
*
|
||||
* @param ranges the descriptions of the character ranges
|
||||
* @throws IllegalArgumentException if the number of ranges exceeds the
|
||||
* limit of {@link java.lang.classfile##u2 u2}
|
||||
*/
|
||||
static CharacterRangeTableAttribute of(List<CharacterRangeInfo> ranges) {
|
||||
return new UnboundAttribute.UnboundCharacterRangeTableAttribute(ranges);
|
||||
|
||||
@ -77,6 +77,8 @@ public sealed interface ExceptionsAttribute
|
||||
/**
|
||||
* {@return an {@code Exceptions} attribute}
|
||||
* @param exceptions the exceptions that may be thrown from this method
|
||||
* @throws IllegalArgumentException if the number of exceptions exceeds the
|
||||
* limit of {@link java.lang.classfile##u2 u2}
|
||||
*/
|
||||
static ExceptionsAttribute of(List<ClassEntry> exceptions) {
|
||||
return new UnboundAttribute.UnboundExceptionsAttribute(exceptions);
|
||||
@ -85,6 +87,8 @@ public sealed interface ExceptionsAttribute
|
||||
/**
|
||||
* {@return an {@code Exceptions} attribute}
|
||||
* @param exceptions the exceptions that may be thrown from this method
|
||||
* @throws IllegalArgumentException if the number of exceptions exceeds the
|
||||
* limit of {@link java.lang.classfile##u2 u2}
|
||||
*/
|
||||
static ExceptionsAttribute of(ClassEntry... exceptions) {
|
||||
return of(List.of(exceptions));
|
||||
@ -93,6 +97,8 @@ public sealed interface ExceptionsAttribute
|
||||
/**
|
||||
* {@return an {@code Exceptions} attribute}
|
||||
* @param exceptions the exceptions that may be thrown from this method
|
||||
* @throws IllegalArgumentException if the number of exceptions exceeds the
|
||||
* limit of {@link java.lang.classfile##u2 u2}
|
||||
*/
|
||||
static ExceptionsAttribute ofSymbols(List<ClassDesc> exceptions) {
|
||||
return of(Util.entryList(exceptions));
|
||||
@ -101,6 +107,8 @@ public sealed interface ExceptionsAttribute
|
||||
/**
|
||||
* {@return an {@code Exceptions} attribute}
|
||||
* @param exceptions the exceptions that may be thrown from this method
|
||||
* @throws IllegalArgumentException if the number of exceptions exceeds the
|
||||
* limit of {@link java.lang.classfile##u2 u2}
|
||||
*/
|
||||
static ExceptionsAttribute ofSymbols(ClassDesc... exceptions) {
|
||||
return ofSymbols(Arrays.asList(exceptions));
|
||||
|
||||
@ -65,6 +65,8 @@ public sealed interface InnerClassesAttribute
|
||||
/**
|
||||
* {@return an {@code InnerClasses} attribute}
|
||||
* @param innerClasses descriptions of the nested classes
|
||||
* @throws IllegalArgumentException if the number of descriptions exceeds
|
||||
* the limit of {@link java.lang.classfile##u2 u2}
|
||||
*/
|
||||
static InnerClassesAttribute of(List<InnerClassInfo> innerClasses) {
|
||||
return new UnboundAttribute.UnboundInnerClassesAttribute(innerClasses);
|
||||
@ -73,6 +75,8 @@ public sealed interface InnerClassesAttribute
|
||||
/**
|
||||
* {@return an {@code InnerClasses} attribute}
|
||||
* @param innerClasses descriptions of the nested classes
|
||||
* @throws IllegalArgumentException if the number of descriptions exceeds
|
||||
* the limit of {@link java.lang.classfile##u2 u2}
|
||||
*/
|
||||
static InnerClassesAttribute of(InnerClassInfo... innerClasses) {
|
||||
return new UnboundAttribute.UnboundInnerClassesAttribute(List.of(innerClasses));
|
||||
|
||||
@ -79,6 +79,8 @@ public sealed interface LineNumberTableAttribute
|
||||
* order instead.
|
||||
*
|
||||
* @param lines the line number descriptions
|
||||
* @throws IllegalArgumentException if the number of descriptions exceeds
|
||||
* the limit of {@link java.lang.classfile##u2 u2}
|
||||
*/
|
||||
static LineNumberTableAttribute of(List<LineNumberInfo> lines) {
|
||||
return new UnboundAttribute.UnboundLineNumberTableAttribute(lines);
|
||||
|
||||
@ -83,6 +83,8 @@ public sealed interface LocalVariableTableAttribute
|
||||
* {@link CodeBuilder#localVariable CodeBuilder::localVariable} instead.
|
||||
*
|
||||
* @param locals the local variable descriptions
|
||||
* @throws IllegalArgumentException if the number of descriptions exceeds
|
||||
* the limit of {@link java.lang.classfile##u2 u2}
|
||||
*/
|
||||
static LocalVariableTableAttribute of(List<LocalVariableInfo> locals) {
|
||||
return new UnboundAttribute.UnboundLocalVariableTableAttribute(locals);
|
||||
|
||||
@ -79,6 +79,8 @@ public sealed interface LocalVariableTypeTableAttribute
|
||||
/**
|
||||
* {@return a {@code LocalVariableTypeTable} attribute}
|
||||
* @param locals the local variable descriptions
|
||||
* @throws IllegalArgumentException if the number of descriptions exceeds
|
||||
* the limit of {@link java.lang.classfile##u2 u2}
|
||||
*/
|
||||
static LocalVariableTypeTableAttribute of(List<LocalVariableTypeInfo> locals) {
|
||||
return new UnboundAttribute.UnboundLocalVariableTypeTableAttribute(locals);
|
||||
|
||||
@ -68,6 +68,8 @@ public sealed interface MethodParametersAttribute
|
||||
/**
|
||||
* {@return a {@code MethodParameters} attribute}
|
||||
* @param parameters the method parameter descriptions
|
||||
* @throws IllegalArgumentException if the number of parameters exceeds the
|
||||
* limit of {@link java.lang.classfile##u1 u1}
|
||||
*/
|
||||
static MethodParametersAttribute of(List<MethodParameterInfo> parameters) {
|
||||
return new UnboundAttribute.UnboundMethodParametersAttribute(parameters);
|
||||
@ -76,6 +78,8 @@ public sealed interface MethodParametersAttribute
|
||||
/**
|
||||
* {@return a {@code MethodParameters} attribute}
|
||||
* @param parameters the method parameter descriptions
|
||||
* @throws IllegalArgumentException if the number of parameters exceeds the
|
||||
* limit of {@link java.lang.classfile##u1 u1}
|
||||
*/
|
||||
static MethodParametersAttribute of(MethodParameterInfo... parameters) {
|
||||
return of(List.of(parameters));
|
||||
|
||||
@ -171,7 +171,8 @@ public sealed interface ModuleAttribute
|
||||
* @param uses the consumed services
|
||||
* @param provides the provided services
|
||||
* @throws IllegalArgumentException if {@code moduleFlags} is not {@link
|
||||
* java.lang.classfile##u2 u2}
|
||||
* java.lang.classfile##u2 u2} or any of the collections has a size
|
||||
* over the limit of {@link java.lang.classfile##u2 u2}
|
||||
*/
|
||||
static ModuleAttribute of(ModuleEntry moduleName, int moduleFlags,
|
||||
Utf8Entry moduleVersion,
|
||||
@ -188,6 +189,9 @@ public sealed interface ModuleAttribute
|
||||
*
|
||||
* @param moduleName the module name
|
||||
* @param attrHandler a handler that receives a {@link ModuleAttributeBuilder}
|
||||
* @throws IllegalArgumentException if the information from the handler exceeds
|
||||
* the {@code class} file format limit, such as a list with size
|
||||
* over the limit of {@link java.lang.classfile##u2 u2}
|
||||
*/
|
||||
static ModuleAttribute of(ModuleDesc moduleName,
|
||||
Consumer<ModuleAttributeBuilder> attrHandler) {
|
||||
@ -296,6 +300,8 @@ public sealed interface ModuleAttribute
|
||||
* @param exportsFlagsMask the export flags
|
||||
* @param exportsToModules the modules to export to, or empty for an unqualified export
|
||||
* @return this builder
|
||||
* @throws IllegalArgumentException if the number of modules exceeds
|
||||
* the limit of {@link java.lang.classfile##u2 u2}
|
||||
*/
|
||||
ModuleAttributeBuilder exports(PackageDesc pkge, int exportsFlagsMask, ModuleDesc... exportsToModules);
|
||||
|
||||
@ -307,7 +313,9 @@ public sealed interface ModuleAttribute
|
||||
* @param exportsToModules the modules to export to, or empty for an unqualified export
|
||||
* @return this builder
|
||||
* @throws IllegalArgumentException if any flag cannot be applied to the
|
||||
* {@link AccessFlag.Location#MODULE_EXPORTS} location
|
||||
* {@link AccessFlag.Location#MODULE_EXPORTS} location or the
|
||||
* number of modules exceeds the limit of {@link
|
||||
* java.lang.classfile##u2 u2}
|
||||
*/
|
||||
default ModuleAttributeBuilder exports(PackageDesc pkge, Collection<AccessFlag> exportsFlags, ModuleDesc... exportsToModules) {
|
||||
return exports(pkge, Util.flagsToBits(AccessFlag.Location.MODULE_EXPORTS, exportsFlags), exportsToModules);
|
||||
@ -333,6 +341,8 @@ public sealed interface ModuleAttribute
|
||||
* @param opensFlagsMask the open package flags
|
||||
* @param opensToModules the modules to open to, or empty for an unqualified open
|
||||
* @return this builder
|
||||
* @throws IllegalArgumentException if the number of modules exceeds the
|
||||
* limit of {@link java.lang.classfile##u2 u2}
|
||||
*/
|
||||
ModuleAttributeBuilder opens(PackageDesc pkge, int opensFlagsMask, ModuleDesc... opensToModules);
|
||||
|
||||
@ -349,7 +359,9 @@ public sealed interface ModuleAttribute
|
||||
* @param opensToModules the modules to open to, or empty for an unqualified open
|
||||
* @return this builder
|
||||
* @throws IllegalArgumentException if any flag cannot be applied to the
|
||||
* {@link AccessFlag.Location#MODULE_OPENS} location
|
||||
* {@link AccessFlag.Location#MODULE_OPENS} location, or if the
|
||||
* number of modules exceeds the limit of {@link
|
||||
* java.lang.classfile##u2 u2}
|
||||
*/
|
||||
default ModuleAttributeBuilder opens(PackageDesc pkge, Collection<AccessFlag> opensFlags, ModuleDesc... opensToModules) {
|
||||
return opens(pkge, Util.flagsToBits(AccessFlag.Location.MODULE_OPENS, opensFlags), opensToModules);
|
||||
@ -391,7 +403,10 @@ public sealed interface ModuleAttribute
|
||||
* @param service the service class provided
|
||||
* @param implClasses the implementation classes
|
||||
* @return this builder
|
||||
* @throws IllegalArgumentException if {@code service} or any of the {@code implClasses} represents a primitive type
|
||||
* @throws IllegalArgumentException if {@code service} or any of the
|
||||
* {@code implClasses} represents a primitive type, or the
|
||||
* number of implementations exceeds the limit of {@link
|
||||
* java.lang.classfile##u2 u2}
|
||||
*/
|
||||
ModuleAttributeBuilder provides(ClassDesc service, ClassDesc... implClasses);
|
||||
|
||||
|
||||
@ -104,7 +104,8 @@ public sealed interface ModuleExportInfo
|
||||
* @param exportsTo the modules to which this package is exported, or empty
|
||||
* if this is an unqualified export
|
||||
* @throws IllegalArgumentException if {@code exportFlags} is not {@link
|
||||
* java.lang.classfile##u2 u2}
|
||||
* java.lang.classfile##u2 u2} or if the number of modules exceeds
|
||||
* the limit of {@link java.lang.classfile##u2 u2}
|
||||
*/
|
||||
static ModuleExportInfo of(PackageEntry exports, int exportFlags,
|
||||
List<ModuleEntry> exportsTo) {
|
||||
@ -119,7 +120,9 @@ public sealed interface ModuleExportInfo
|
||||
* @param exportsTo the modules to which this package is exported, or empty
|
||||
* if this is an unqualified export
|
||||
* @throws IllegalArgumentException if any flag cannot be applied to the
|
||||
* {@link AccessFlag.Location#MODULE_EXPORTS} location
|
||||
* {@link AccessFlag.Location#MODULE_EXPORTS} location, or if the
|
||||
* number of modules exceeds the limit of {@link
|
||||
* java.lang.classfile##u2 u2}
|
||||
*/
|
||||
static ModuleExportInfo of(PackageEntry exports, Collection<AccessFlag> exportFlags,
|
||||
List<ModuleEntry> exportsTo) {
|
||||
@ -134,7 +137,8 @@ public sealed interface ModuleExportInfo
|
||||
* @param exportsTo the modules to which this package is exported, or empty
|
||||
* if this is an unqualified export
|
||||
* @throws IllegalArgumentException if {@code exportFlags} is not {@link
|
||||
* java.lang.classfile##u2 u2}
|
||||
* java.lang.classfile##u2 u2} or if the number of modules exceeds
|
||||
* the limit of {@link java.lang.classfile##u2 u2}
|
||||
*/
|
||||
static ModuleExportInfo of(PackageEntry exports,
|
||||
int exportFlags,
|
||||
@ -150,7 +154,9 @@ public sealed interface ModuleExportInfo
|
||||
* @param exportsTo the modules to which this package is exported, or empty
|
||||
* if this is an unqualified export
|
||||
* @throws IllegalArgumentException if any flag cannot be applied to the
|
||||
* {@link AccessFlag.Location#MODULE_EXPORTS} location
|
||||
* {@link AccessFlag.Location#MODULE_EXPORTS} location, or if the
|
||||
* number of modules exceeds the limit of {@link
|
||||
* java.lang.classfile##u2 u2}
|
||||
*/
|
||||
static ModuleExportInfo of(PackageEntry exports,
|
||||
Collection<AccessFlag> exportFlags,
|
||||
@ -166,7 +172,8 @@ public sealed interface ModuleExportInfo
|
||||
* @param exportsTo the modules to which this package is exported, or empty
|
||||
* if this is an unqualified export
|
||||
* @throws IllegalArgumentException if {@code exportFlags} is not {@link
|
||||
* java.lang.classfile##u2 u2}
|
||||
* java.lang.classfile##u2 u2} or if the number of modules exceeds
|
||||
* the limit of {@link java.lang.classfile##u2 u2}
|
||||
*/
|
||||
static ModuleExportInfo of(PackageDesc exports, int exportFlags,
|
||||
List<ModuleDesc> exportsTo) {
|
||||
@ -183,7 +190,9 @@ public sealed interface ModuleExportInfo
|
||||
* @param exportsTo the modules to which this package is exported, or empty
|
||||
* if this is an unqualified export
|
||||
* @throws IllegalArgumentException if any flag cannot be applied to the
|
||||
* {@link AccessFlag.Location#MODULE_EXPORTS} location
|
||||
* {@link AccessFlag.Location#MODULE_EXPORTS} location, or if the
|
||||
* number of modules exceeds the limit of {@link
|
||||
* java.lang.classfile##u2 u2}
|
||||
*/
|
||||
static ModuleExportInfo of(PackageDesc exports, Collection<AccessFlag> exportFlags,
|
||||
List<ModuleDesc> exportsTo) {
|
||||
@ -198,7 +207,8 @@ public sealed interface ModuleExportInfo
|
||||
* @param exportsTo the modules to which this package is exported, or empty
|
||||
* if this is an unqualified export
|
||||
* @throws IllegalArgumentException if {@code exportFlags} is not {@link
|
||||
* java.lang.classfile##u2 u2}
|
||||
* java.lang.classfile##u2 u2} or if the number of modules exceeds
|
||||
* the limit of {@link java.lang.classfile##u2 u2}
|
||||
*/
|
||||
static ModuleExportInfo of(PackageDesc exports,
|
||||
int exportFlags,
|
||||
@ -214,7 +224,9 @@ public sealed interface ModuleExportInfo
|
||||
* @param exportsTo the modules to which this package is exported, or empty
|
||||
* if this is an unqualified export
|
||||
* @throws IllegalArgumentException if any flag cannot be applied to the
|
||||
* {@link AccessFlag.Location#MODULE_EXPORTS} location
|
||||
* {@link AccessFlag.Location#MODULE_EXPORTS} location, or if the
|
||||
* number of modules exceeds the limit of {@link
|
||||
* java.lang.classfile##u2 u2}
|
||||
*/
|
||||
static ModuleExportInfo of(PackageDesc exports,
|
||||
Collection<AccessFlag> exportFlags,
|
||||
|
||||
@ -96,6 +96,8 @@ public sealed interface ModuleHashesAttribute
|
||||
* {@return a {@code ModuleHashes} attribute}
|
||||
* @param algorithm the hashing algorithm
|
||||
* @param hashes the hash descriptions
|
||||
* @throws IllegalArgumentException if the number of descriptions exceeds
|
||||
* the limit of {@link java.lang.classfile##u2 u2}
|
||||
*/
|
||||
static ModuleHashesAttribute of(String algorithm,
|
||||
List<ModuleHashInfo> hashes) {
|
||||
@ -106,6 +108,8 @@ public sealed interface ModuleHashesAttribute
|
||||
* {@return a {@code ModuleHashes} attribute}
|
||||
* @param algorithm the hashing algorithm
|
||||
* @param hashes the hash descriptions
|
||||
* @throws IllegalArgumentException if the number of descriptions exceeds
|
||||
* the limit of {@link java.lang.classfile##u2 u2}
|
||||
*/
|
||||
static ModuleHashesAttribute of(String algorithm,
|
||||
ModuleHashInfo... hashes) {
|
||||
@ -116,6 +120,8 @@ public sealed interface ModuleHashesAttribute
|
||||
* {@return a {@code ModuleHashes} attribute}
|
||||
* @param algorithm the hashing algorithm
|
||||
* @param hashes the hash descriptions
|
||||
* @throws IllegalArgumentException if the number of descriptions exceeds
|
||||
* the limit of {@link java.lang.classfile##u2 u2}
|
||||
*/
|
||||
static ModuleHashesAttribute of(Utf8Entry algorithm,
|
||||
List<ModuleHashInfo> hashes) {
|
||||
@ -126,6 +132,8 @@ public sealed interface ModuleHashesAttribute
|
||||
* {@return a {@code ModuleHashes} attribute}
|
||||
* @param algorithm the hashing algorithm
|
||||
* @param hashes the hash descriptions
|
||||
* @throws IllegalArgumentException if the number of descriptions exceeds
|
||||
* the limit of {@link java.lang.classfile##u2 u2}
|
||||
*/
|
||||
static ModuleHashesAttribute of(Utf8Entry algorithm,
|
||||
ModuleHashInfo... hashes) {
|
||||
|
||||
@ -110,7 +110,8 @@ public sealed interface ModuleOpenInfo
|
||||
* @param opensTo the modules to which this package is opened, or empty if
|
||||
* this is an unqualified open
|
||||
* @throws IllegalArgumentException if {@code opensFlags} is not {@link
|
||||
* java.lang.classfile##u2 u2}
|
||||
* java.lang.classfile##u2 u2} or if the number of modules exceeds
|
||||
* the limit of {@link java.lang.classfile##u2 u2}
|
||||
*/
|
||||
static ModuleOpenInfo of(PackageEntry opens, int opensFlags,
|
||||
List<ModuleEntry> opensTo) {
|
||||
@ -125,7 +126,8 @@ public sealed interface ModuleOpenInfo
|
||||
* @param opensTo the modules to which this package is opened, or empty if
|
||||
* this is an unqualified open
|
||||
* @throws IllegalArgumentException if any flag cannot be applied to the
|
||||
* {@link AccessFlag.Location#MODULE_OPENS} location
|
||||
* {@link AccessFlag.Location#MODULE_OPENS} location, or the number
|
||||
* of modules exceeds the limit of {@link java.lang.classfile##u2 u2}
|
||||
*/
|
||||
static ModuleOpenInfo of(PackageEntry opens, Collection<AccessFlag> opensFlags,
|
||||
List<ModuleEntry> opensTo) {
|
||||
@ -140,7 +142,8 @@ public sealed interface ModuleOpenInfo
|
||||
* @param opensTo the modules to which this package is opened, or empty if
|
||||
* this is an unqualified open
|
||||
* @throws IllegalArgumentException if {@code opensFlags} is not {@link
|
||||
* java.lang.classfile##u2 u2}
|
||||
* java.lang.classfile##u2 u2} or if the number of modules exceeds
|
||||
* the limit of {@link java.lang.classfile##u2 u2}
|
||||
*/
|
||||
static ModuleOpenInfo of(PackageEntry opens,
|
||||
int opensFlags,
|
||||
@ -156,7 +159,8 @@ public sealed interface ModuleOpenInfo
|
||||
* @param opensTo the modules to which this package is opened, or empty if
|
||||
* this is an unqualified open
|
||||
* @throws IllegalArgumentException if any flag cannot be applied to the
|
||||
* {@link AccessFlag.Location#MODULE_OPENS} location
|
||||
* {@link AccessFlag.Location#MODULE_OPENS} location, or the number
|
||||
* of modules exceeds the limit of {@link java.lang.classfile##u2 u2}
|
||||
*/
|
||||
static ModuleOpenInfo of(PackageEntry opens,
|
||||
Collection<AccessFlag> opensFlags,
|
||||
@ -171,7 +175,8 @@ public sealed interface ModuleOpenInfo
|
||||
* @param opensTo the modules to which this package is opened, if it is a
|
||||
* qualified open, or empty
|
||||
* @throws IllegalArgumentException if {@code opensFlags} is not {@link
|
||||
* java.lang.classfile##u2 u2}
|
||||
* java.lang.classfile##u2 u2} or if the number of modules exceeds
|
||||
* the limit of {@link java.lang.classfile##u2 u2}
|
||||
*/
|
||||
static ModuleOpenInfo of(PackageDesc opens, int opensFlags,
|
||||
List<ModuleDesc> opensTo) {
|
||||
@ -187,7 +192,8 @@ public sealed interface ModuleOpenInfo
|
||||
* @param opensTo the modules to which this package is opened, if it is a
|
||||
* qualified open, or empty
|
||||
* @throws IllegalArgumentException if any flag cannot be applied to the
|
||||
* {@link AccessFlag.Location#MODULE_OPENS} location
|
||||
* {@link AccessFlag.Location#MODULE_OPENS} location, or the number
|
||||
* of modules exceeds the limit of {@link java.lang.classfile##u2 u2}
|
||||
*/
|
||||
static ModuleOpenInfo of(PackageDesc opens, Collection<AccessFlag> opensFlags,
|
||||
List<ModuleDesc> opensTo) {
|
||||
@ -201,7 +207,8 @@ public sealed interface ModuleOpenInfo
|
||||
* @param opensTo the packages to which this package is opened, or empty if
|
||||
* this is an unqualified open
|
||||
* @throws IllegalArgumentException if {@code opensFlags} is not {@link
|
||||
* java.lang.classfile##u2 u2}
|
||||
* java.lang.classfile##u2 u2} or if the number of modules exceeds
|
||||
* the limit of {@link java.lang.classfile##u2 u2}
|
||||
*/
|
||||
static ModuleOpenInfo of(PackageDesc opens,
|
||||
int opensFlags,
|
||||
@ -216,7 +223,8 @@ public sealed interface ModuleOpenInfo
|
||||
* @param opensTo the packages to which this package is opened, or empty if
|
||||
* this is an unqualified open
|
||||
* @throws IllegalArgumentException if any flag cannot be applied to the
|
||||
* {@link AccessFlag.Location#MODULE_OPENS} location
|
||||
* {@link AccessFlag.Location#MODULE_OPENS} location, or the number
|
||||
* of modules exceeds the limit of {@link java.lang.classfile##u2 u2}
|
||||
*/
|
||||
static ModuleOpenInfo of(PackageDesc opens,
|
||||
Collection<AccessFlag> opensFlags,
|
||||
|
||||
@ -74,6 +74,8 @@ public sealed interface ModulePackagesAttribute
|
||||
/**
|
||||
* {@return a {@code ModulePackages} attribute}
|
||||
* @param packages the packages
|
||||
* @throws IllegalArgumentException if the number of packages exceeds the
|
||||
* limit of {@link java.lang.classfile##u2 u2}
|
||||
*/
|
||||
static ModulePackagesAttribute of(List<PackageEntry> packages) {
|
||||
return new UnboundAttribute.UnboundModulePackagesAttribute(packages);
|
||||
@ -82,6 +84,8 @@ public sealed interface ModulePackagesAttribute
|
||||
/**
|
||||
* {@return a {@code ModulePackages} attribute}
|
||||
* @param packages the packages
|
||||
* @throws IllegalArgumentException if the number of packages exceeds the
|
||||
* limit of {@link java.lang.classfile##u2 u2}
|
||||
*/
|
||||
static ModulePackagesAttribute of(PackageEntry... packages) {
|
||||
return of(List.of(packages));
|
||||
@ -90,6 +94,8 @@ public sealed interface ModulePackagesAttribute
|
||||
/**
|
||||
* {@return a {@code ModulePackages} attribute}
|
||||
* @param packages the packages
|
||||
* @throws IllegalArgumentException if the number of packages exceeds the
|
||||
* limit of {@link java.lang.classfile##u2 u2}
|
||||
*/
|
||||
static ModulePackagesAttribute ofNames(List<PackageDesc> packages) {
|
||||
var p = new PackageEntry[packages.size()];
|
||||
@ -102,6 +108,8 @@ public sealed interface ModulePackagesAttribute
|
||||
/**
|
||||
* {@return a {@code ModulePackages} attribute}
|
||||
* @param packages the packages
|
||||
* @throws IllegalArgumentException if the number of packages exceeds the
|
||||
* limit of {@link java.lang.classfile##u2 u2}
|
||||
*/
|
||||
static ModulePackagesAttribute ofNames(PackageDesc... packages) {
|
||||
// List view, since ref to packages is temporary
|
||||
|
||||
@ -64,6 +64,8 @@ public sealed interface ModuleProvideInfo
|
||||
* {@return a service provision description}
|
||||
* @param provides the service class interface
|
||||
* @param providesWith the service class implementations, must not be empty
|
||||
* @throws IllegalArgumentException if the number of implementations exceeds
|
||||
* the limit of {@link java.lang.classfile##u2 u2}
|
||||
*/
|
||||
static ModuleProvideInfo of(ClassEntry provides,
|
||||
List<ClassEntry> providesWith) {
|
||||
@ -74,6 +76,8 @@ public sealed interface ModuleProvideInfo
|
||||
* {@return a service provision description}
|
||||
* @param provides the service class interface
|
||||
* @param providesWith the service class implementations, must not be empty
|
||||
* @throws IllegalArgumentException if the number of implementations exceeds
|
||||
* the limit of {@link java.lang.classfile##u2 u2}
|
||||
*/
|
||||
static ModuleProvideInfo of(ClassEntry provides,
|
||||
ClassEntry... providesWith) {
|
||||
@ -85,7 +89,8 @@ public sealed interface ModuleProvideInfo
|
||||
* @param provides the service class interface
|
||||
* @param providesWith the service class implementations, must not be empty
|
||||
* @throws IllegalArgumentException if {@code provides} or any of {@code
|
||||
* providesWith} represents a primitive type
|
||||
* providesWith} represents a primitive type, or the number of
|
||||
* implementations exceeds the limit of {@link java.lang.classfile##u2 u2}
|
||||
*/
|
||||
static ModuleProvideInfo of(ClassDesc provides,
|
||||
List<ClassDesc> providesWith) {
|
||||
@ -97,7 +102,8 @@ public sealed interface ModuleProvideInfo
|
||||
* @param provides the service class interface
|
||||
* @param providesWith the service class implementations, must not be empty
|
||||
* @throws IllegalArgumentException if {@code provides} or any of {@code
|
||||
* providesWith} represents a primitive type
|
||||
* providesWith} represents a primitive type, or the number of
|
||||
* implementations exceeds the limit of {@link java.lang.classfile##u2 u2}
|
||||
*/
|
||||
static ModuleProvideInfo of(ClassDesc provides,
|
||||
ClassDesc... providesWith) {
|
||||
|
||||
@ -72,6 +72,8 @@ public sealed interface NestMembersAttribute extends Attribute<NestMembersAttrib
|
||||
* {@return a {@code NestMembers} attribute}
|
||||
*
|
||||
* @param nestMembers the member classes of the nest
|
||||
* @throws IllegalArgumentException if the number of member classes exceeds
|
||||
* the limit of {@link java.lang.classfile##u2 u2}
|
||||
*/
|
||||
static NestMembersAttribute of(List<ClassEntry> nestMembers) {
|
||||
return new UnboundAttribute.UnboundNestMembersAttribute(nestMembers);
|
||||
@ -81,6 +83,8 @@ public sealed interface NestMembersAttribute extends Attribute<NestMembersAttrib
|
||||
* {@return a {@code NestMembers} attribute}
|
||||
*
|
||||
* @param nestMembers the member classes of the nest
|
||||
* @throws IllegalArgumentException if the number of member classes exceeds
|
||||
* the limit of {@link java.lang.classfile##u2 u2}
|
||||
*/
|
||||
static NestMembersAttribute of(ClassEntry... nestMembers) {
|
||||
return of(List.of(nestMembers));
|
||||
@ -90,7 +94,9 @@ public sealed interface NestMembersAttribute extends Attribute<NestMembersAttrib
|
||||
* {@return a {@code NestMembers} attribute}
|
||||
*
|
||||
* @param nestMembers the member classes of the nest
|
||||
* @throws IllegalArgumentException if any of {@code nestMembers} is primitive
|
||||
* @throws IllegalArgumentException if any of {@code nestMembers} is primitive,
|
||||
* or if the number of member classes exceeds the limit of {@link
|
||||
* java.lang.classfile##u2 u2}
|
||||
*/
|
||||
static NestMembersAttribute ofSymbols(List<ClassDesc> nestMembers) {
|
||||
return of(Util.entryList(nestMembers));
|
||||
@ -100,7 +106,9 @@ public sealed interface NestMembersAttribute extends Attribute<NestMembersAttrib
|
||||
* {@return a {@code NestMembers} attribute}
|
||||
*
|
||||
* @param nestMembers the member classes of the nest
|
||||
* @throws IllegalArgumentException if any of {@code nestMembers} is primitive
|
||||
* @throws IllegalArgumentException if any of {@code nestMembers} is primitive,
|
||||
* or if the number of member classes exceeds the limit of {@link
|
||||
* java.lang.classfile##u2 u2}
|
||||
*/
|
||||
static NestMembersAttribute ofSymbols(ClassDesc... nestMembers) {
|
||||
// List version does defensive copy
|
||||
|
||||
@ -77,6 +77,8 @@ public sealed interface PermittedSubclassesAttribute
|
||||
* {@return a {@code PermittedSubclasses} attribute}
|
||||
*
|
||||
* @param permittedSubclasses the permitted subclasses or subinterfaces
|
||||
* @throws IllegalArgumentException if the number of permitted subclasses
|
||||
* or subinterfaces exceeds the limit of {@link java.lang.classfile##u2 u2}
|
||||
*/
|
||||
static PermittedSubclassesAttribute of(List<ClassEntry> permittedSubclasses) {
|
||||
return new UnboundAttribute.UnboundPermittedSubclassesAttribute(permittedSubclasses);
|
||||
@ -86,6 +88,8 @@ public sealed interface PermittedSubclassesAttribute
|
||||
* {@return a {@code PermittedSubclasses} attribute}
|
||||
*
|
||||
* @param permittedSubclasses the permitted subclasses or subinterfaces
|
||||
* @throws IllegalArgumentException if the number of permitted subclasses
|
||||
* or subinterfaces exceeds the limit of {@link java.lang.classfile##u2 u2}
|
||||
*/
|
||||
static PermittedSubclassesAttribute of(ClassEntry... permittedSubclasses) {
|
||||
return of(List.of(permittedSubclasses));
|
||||
@ -95,7 +99,9 @@ public sealed interface PermittedSubclassesAttribute
|
||||
* {@return a {@code PermittedSubclasses} attribute}
|
||||
*
|
||||
* @param permittedSubclasses the permitted subclasses or subinterfaces
|
||||
* @throws IllegalArgumentException if any of {@code permittedSubclasses} is primitive
|
||||
* @throws IllegalArgumentException if any of {@code permittedSubclasses} is primitive,
|
||||
* or if the number of permitted subclasses or subinterfaces exceeds
|
||||
* the limit of {@link java.lang.classfile##u2 u2}
|
||||
*/
|
||||
static PermittedSubclassesAttribute ofSymbols(List<ClassDesc> permittedSubclasses) {
|
||||
return of(Util.entryList(permittedSubclasses));
|
||||
@ -105,7 +111,9 @@ public sealed interface PermittedSubclassesAttribute
|
||||
* {@return a {@code PermittedSubclasses} attribute}
|
||||
*
|
||||
* @param permittedSubclasses the permitted subclasses or subinterfaces
|
||||
* @throws IllegalArgumentException if any of {@code permittedSubclasses} is primitive
|
||||
* @throws IllegalArgumentException if any of {@code permittedSubclasses} is primitive,
|
||||
* or if the number of permitted subclasses or subinterfaces exceeds
|
||||
* the limit of {@link java.lang.classfile##u2 u2}
|
||||
*/
|
||||
static PermittedSubclassesAttribute ofSymbols(ClassDesc... permittedSubclasses) {
|
||||
// List version does defensive copy
|
||||
|
||||
@ -68,6 +68,8 @@ public sealed interface RecordAttribute extends Attribute<RecordAttribute>, Clas
|
||||
* {@return a {@code Record} attribute}
|
||||
*
|
||||
* @param components the record components
|
||||
* @throws IllegalArgumentException if the number of record components
|
||||
* exceeds the limit of {@link java.lang.classfile##u2 u2}
|
||||
*/
|
||||
static RecordAttribute of(List<RecordComponentInfo> components) {
|
||||
return new UnboundAttribute.UnboundRecordAttribute(components);
|
||||
@ -77,6 +79,8 @@ public sealed interface RecordAttribute extends Attribute<RecordAttribute>, Clas
|
||||
* {@return a {@code Record} attribute}
|
||||
*
|
||||
* @param components the record components
|
||||
* @throws IllegalArgumentException if the number of record components
|
||||
* exceeds the limit of {@link java.lang.classfile##u2 u2}
|
||||
*/
|
||||
static RecordAttribute of(RecordComponentInfo... components) {
|
||||
return of(List.of(components));
|
||||
|
||||
@ -90,6 +90,8 @@ public sealed interface RecordComponentInfo
|
||||
* @param name the component name
|
||||
* @param descriptor the component field descriptor string
|
||||
* @param attributes the component attributes
|
||||
* @throws IllegalArgumentException if the number of attributes exceeds the
|
||||
* limit of {@link java.lang.classfile##u2 u2}
|
||||
*/
|
||||
static RecordComponentInfo of(Utf8Entry name,
|
||||
Utf8Entry descriptor,
|
||||
@ -103,6 +105,8 @@ public sealed interface RecordComponentInfo
|
||||
* @param name the component name
|
||||
* @param descriptor the component field descriptor sting
|
||||
* @param attributes the component attributes
|
||||
* @throws IllegalArgumentException if the number of attributes exceeds the
|
||||
* limit of {@link java.lang.classfile##u2 u2}
|
||||
*/
|
||||
static RecordComponentInfo of(Utf8Entry name,
|
||||
Utf8Entry descriptor,
|
||||
@ -116,6 +120,8 @@ public sealed interface RecordComponentInfo
|
||||
* @param name the component name
|
||||
* @param descriptor the component symbolic field descriptor
|
||||
* @param attributes the component attributes
|
||||
* @throws IllegalArgumentException if the number of attributes exceeds the
|
||||
* limit of {@link java.lang.classfile##u2 u2}
|
||||
*/
|
||||
static RecordComponentInfo of(String name,
|
||||
ClassDesc descriptor,
|
||||
@ -131,6 +137,8 @@ public sealed interface RecordComponentInfo
|
||||
* @param name the component name
|
||||
* @param descriptor the component symbolic field descriptor
|
||||
* @param attributes the component attributes
|
||||
* @throws IllegalArgumentException if the number of attributes exceeds the
|
||||
* limit of {@link java.lang.classfile##u2 u2}
|
||||
*/
|
||||
static RecordComponentInfo of(String name,
|
||||
ClassDesc descriptor,
|
||||
|
||||
@ -73,6 +73,8 @@ public sealed interface RuntimeInvisibleAnnotationsAttribute
|
||||
* {@return a {@code RuntimeInvisibleAnnotations} attribute}
|
||||
*
|
||||
* @param annotations the annotations
|
||||
* @throws IllegalArgumentException if the number of annotations exceeds
|
||||
* the limit of {@link java.lang.classfile##u2 u2}
|
||||
*/
|
||||
static RuntimeInvisibleAnnotationsAttribute of(List<Annotation> annotations) {
|
||||
return new UnboundAttribute.UnboundRuntimeInvisibleAnnotationsAttribute(annotations);
|
||||
@ -82,6 +84,8 @@ public sealed interface RuntimeInvisibleAnnotationsAttribute
|
||||
* {@return a {@code RuntimeInvisibleAnnotations} attribute}
|
||||
*
|
||||
* @param annotations the annotations
|
||||
* @throws IllegalArgumentException if the number of annotations exceeds
|
||||
* the limit of {@link java.lang.classfile##u2 u2}
|
||||
*/
|
||||
static RuntimeInvisibleAnnotationsAttribute of(Annotation... annotations) {
|
||||
return of(List.of(annotations));
|
||||
|
||||
@ -86,6 +86,10 @@ public sealed interface RuntimeInvisibleParameterAnnotationsAttribute
|
||||
* some synthetic or implicit parameters.
|
||||
*
|
||||
* @param parameterAnnotations a list of run-time invisible annotations for each parameter
|
||||
* @throws IllegalArgumentException if the number of parameters exceeds the
|
||||
* limit of {@link java.lang.classfile##u1 u1}, or the number of
|
||||
* annotations on any parameter exceeds the limit of {@link
|
||||
* java.lang.classfile##u2 u2}
|
||||
*/
|
||||
static RuntimeInvisibleParameterAnnotationsAttribute of(List<List<Annotation>> parameterAnnotations) {
|
||||
return new UnboundAttribute.UnboundRuntimeInvisibleParameterAnnotationsAttribute(parameterAnnotations);
|
||||
|
||||
@ -79,6 +79,8 @@ public sealed interface RuntimeInvisibleTypeAnnotationsAttribute
|
||||
* {@return a {@code RuntimeInvisibleTypeAnnotations} attribute}
|
||||
*
|
||||
* @param annotations the annotations
|
||||
* @throws IllegalArgumentException if the number of annotations exceeds the
|
||||
* limit of {@link java.lang.classfile##u2 u2}
|
||||
*/
|
||||
static RuntimeInvisibleTypeAnnotationsAttribute of(List<TypeAnnotation> annotations) {
|
||||
return new UnboundAttribute.UnboundRuntimeInvisibleTypeAnnotationsAttribute(annotations);
|
||||
@ -88,6 +90,8 @@ public sealed interface RuntimeInvisibleTypeAnnotationsAttribute
|
||||
* {@return a {@code RuntimeInvisibleTypeAnnotations} attribute}
|
||||
*
|
||||
* @param annotations the annotations
|
||||
* @throws IllegalArgumentException if the number of annotations exceeds the
|
||||
* limit of {@link java.lang.classfile##u2 u2}
|
||||
*/
|
||||
static RuntimeInvisibleTypeAnnotationsAttribute of(TypeAnnotation... annotations) {
|
||||
return of(List.of(annotations));
|
||||
|
||||
@ -72,6 +72,8 @@ public sealed interface RuntimeVisibleAnnotationsAttribute
|
||||
/**
|
||||
* {@return a {@code RuntimeVisibleAnnotations} attribute}
|
||||
* @param annotations the annotations
|
||||
* @throws IllegalArgumentException if the number of annotations exceeds the
|
||||
* limit of {@link java.lang.classfile##u2 u2}
|
||||
*/
|
||||
static RuntimeVisibleAnnotationsAttribute of(List<Annotation> annotations) {
|
||||
return new UnboundAttribute.UnboundRuntimeVisibleAnnotationsAttribute(annotations);
|
||||
@ -80,6 +82,8 @@ public sealed interface RuntimeVisibleAnnotationsAttribute
|
||||
/**
|
||||
* {@return a {@code RuntimeVisibleAnnotations} attribute}
|
||||
* @param annotations the annotations
|
||||
* @throws IllegalArgumentException if the number of annotations exceeds the
|
||||
* limit of {@link java.lang.classfile##u2 u2}
|
||||
*/
|
||||
static RuntimeVisibleAnnotationsAttribute of(Annotation... annotations) {
|
||||
return of(List.of(annotations));
|
||||
|
||||
@ -88,6 +88,10 @@ public sealed interface RuntimeVisibleParameterAnnotationsAttribute
|
||||
* some synthetic or implicit parameters.
|
||||
*
|
||||
* @param parameterAnnotations a list of run-time visible annotations for each parameter
|
||||
* @throws IllegalArgumentException if the number of parameters exceeds the
|
||||
* limit of {@link java.lang.classfile##u1 u1}, or the number of
|
||||
* annotations on any parameter exceeds the limit of {@link
|
||||
* java.lang.classfile##u2 u2}
|
||||
*/
|
||||
static RuntimeVisibleParameterAnnotationsAttribute of(List<List<Annotation>> parameterAnnotations) {
|
||||
return new UnboundAttribute.UnboundRuntimeVisibleParameterAnnotationsAttribute(parameterAnnotations);
|
||||
|
||||
@ -79,6 +79,8 @@ public sealed interface RuntimeVisibleTypeAnnotationsAttribute
|
||||
* {@return a {@code RuntimeVisibleTypeAnnotations} attribute}
|
||||
*
|
||||
* @param annotations the annotations
|
||||
* @throws IllegalArgumentException if the number of annotations exceeds the
|
||||
* limit of {@link java.lang.classfile##u2 u2}
|
||||
*/
|
||||
static RuntimeVisibleTypeAnnotationsAttribute of(List<TypeAnnotation> annotations) {
|
||||
return new UnboundAttribute.UnboundRuntimeVisibleTypeAnnotationsAttribute(annotations);
|
||||
@ -88,6 +90,8 @@ public sealed interface RuntimeVisibleTypeAnnotationsAttribute
|
||||
* {@return a {@code RuntimeVisibleTypeAnnotations} attribute}
|
||||
*
|
||||
* @param annotations the annotations
|
||||
* @throws IllegalArgumentException if the number of annotations exceeds the
|
||||
* limit of {@link java.lang.classfile##u2 u2}
|
||||
*/
|
||||
static RuntimeVisibleTypeAnnotationsAttribute of(TypeAnnotation... annotations) {
|
||||
return of(List.of(annotations));
|
||||
|
||||
@ -83,6 +83,8 @@ public sealed interface StackMapFrameInfo
|
||||
* @param target the location of the frame
|
||||
* @param locals the complete list of frame locals
|
||||
* @param stack the complete frame stack
|
||||
* @throws IllegalArgumentException if the number of types in {@code locals}
|
||||
* or {@code stack} exceeds the limit of {@link java.lang.classfile##u2 u2}
|
||||
*/
|
||||
public static StackMapFrameInfo of(Label target,
|
||||
List<VerificationTypeInfo> locals,
|
||||
|
||||
@ -75,6 +75,8 @@ public sealed interface StackMapTableAttribute
|
||||
* {@return a stack map table attribute}
|
||||
*
|
||||
* @param entries the stack map frames
|
||||
* @throws IllegalArgumentException if the number of frames exceeds the
|
||||
* limit of {@link java.lang.classfile##u2 u2}
|
||||
*/
|
||||
public static StackMapTableAttribute of(List<StackMapFrameInfo> entries) {
|
||||
return new UnboundAttribute.UnboundStackMapTableAttribute(entries);
|
||||
|
||||
@ -571,6 +571,8 @@ public sealed interface ConstantPoolBuilder
|
||||
*
|
||||
* @param methodReference the bootstrap method
|
||||
* @param arguments the arguments
|
||||
* @throws IllegalArgumentException if the number of arguments exceeds the
|
||||
* limit of {@link java.lang.classfile##u2 u2}
|
||||
*/
|
||||
default BootstrapMethodEntry bsmEntry(DirectMethodHandleDesc methodReference,
|
||||
List<ConstantDesc> arguments) {
|
||||
@ -586,6 +588,8 @@ public sealed interface ConstantPoolBuilder
|
||||
*
|
||||
* @param methodReference the {@code MethodHandleEntry}
|
||||
* @param arguments the list of {@code LoadableConstantEntry}
|
||||
* @throws IllegalArgumentException if the number of arguments exceeds the
|
||||
* limit of {@link java.lang.classfile##u2 u2}
|
||||
* @see BootstrapMethodEntry#bootstrapMethod()
|
||||
* BootstrapMethodEntry::bootstrapMethod
|
||||
* @see BootstrapMethodEntry#arguments() BootstrapMethodEntry::arguments
|
||||
|
||||
@ -54,7 +54,8 @@ import jdk.internal.classfile.impl.AbstractPoolEntry;
|
||||
* Unlike most constant pool entries, a UTF-8 entry is of flexible length: it is
|
||||
* represented as an array structure, with an {@code u2} for the data length in
|
||||
* bytes, followed by that number of bytes of Modified UTF-8 data. It can
|
||||
* represent at most 65535 bytes of data due to the physical restrictions.
|
||||
* represent at most 65535 bytes of data due to the physical restrictions of
|
||||
* {@link java.lang.classfile##u2 u2}.
|
||||
*
|
||||
* @jvms 4.4.7 The {@code CONSTANT_Utf8_info} Structure
|
||||
* @see DataInput##modified-utf-8 Modified UTF-8
|
||||
|
||||
@ -255,7 +255,7 @@
|
||||
* or method of any Class-File API class or interface will cause a {@link
|
||||
* NullPointerException} to be thrown. Additionally,
|
||||
* invoking a method with an array or collection containing a {@code null} element
|
||||
* will cause a {@code NullPointerException}, unless otherwise specified. </p>
|
||||
* will cause a {@code NullPointerException}, unless otherwise specified.
|
||||
*
|
||||
* <h3>Symbolic information</h3>
|
||||
* To describe symbolic information for classes and types, the API uses the
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2022, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -40,7 +40,7 @@ public record AnnotationImpl(Utf8Entry className, List<AnnotationElement> elemen
|
||||
implements Annotation {
|
||||
public AnnotationImpl {
|
||||
requireNonNull(className);
|
||||
elements = List.copyOf(elements);
|
||||
elements = Util.sanitizeU2List(elements);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -189,7 +189,7 @@ public record AnnotationImpl(Utf8Entry className, List<AnnotationElement> elemen
|
||||
public record OfArrayImpl(List<AnnotationValue> values)
|
||||
implements AnnotationValue.OfArray {
|
||||
public OfArrayImpl {
|
||||
values = List.copyOf(values);
|
||||
values = Util.sanitizeU2List(values);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2022, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -66,6 +66,7 @@ public class AttributeHolder {
|
||||
|
||||
public void writeTo(BufWriterImpl buf) {
|
||||
int attributesCount = this.attributesCount;
|
||||
Util.checkU2(attributesCount, "attributes count");
|
||||
buf.writeU2(attributesCount);
|
||||
for (int i = 0; i < attributesCount; i++) {
|
||||
Util.writeAttribute(buf, attributes[i]);
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2022, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -41,13 +41,13 @@ public final class BootstrapMethodEntryImpl implements BootstrapMethodEntry {
|
||||
private final List<LoadableConstantEntry> arguments;
|
||||
|
||||
BootstrapMethodEntryImpl(ConstantPool constantPool, int bsmIndex, int hash,
|
||||
MethodHandleEntryImpl handle,
|
||||
List<LoadableConstantEntry> arguments) {
|
||||
MethodHandleEntryImpl handle,
|
||||
List<LoadableConstantEntry> arguments) {
|
||||
this.index = bsmIndex;
|
||||
this.hash = hash;
|
||||
this.constantPool = constantPool;
|
||||
this.handle = handle;
|
||||
this.arguments = List.copyOf(arguments);
|
||||
this.arguments = Util.sanitizeU2List(arguments);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@ -276,9 +276,7 @@ public final class BufWriterImpl implements BufWriter {
|
||||
int strlen = str.length();
|
||||
int countNonZeroAscii = JLA.countNonZeroAscii(str);
|
||||
int utflen = utfLen(str, countNonZeroAscii);
|
||||
if (utflen > 65535) {
|
||||
throw new IllegalArgumentException("string too long");
|
||||
}
|
||||
Util.checkU2(utflen, "utf8 length");
|
||||
reserveSpace(utflen + 3);
|
||||
|
||||
int offset = this.offset;
|
||||
|
||||
@ -185,14 +185,14 @@ public final class DirectCodeBuilder
|
||||
private void writeExceptionHandlers(BufWriterImpl buf) {
|
||||
int pos = buf.size();
|
||||
int handlersSize = handlers.size();
|
||||
Util.checkU2(handlersSize, "exception handlers");
|
||||
buf.writeU2(handlersSize);
|
||||
if (handlersSize > 0) {
|
||||
writeExceptionHandlers(buf, pos);
|
||||
writeExceptionHandlers(buf, pos, handlersSize);
|
||||
}
|
||||
}
|
||||
|
||||
private void writeExceptionHandlers(BufWriterImpl buf, int pos) {
|
||||
int handlersSize = handlers.size();
|
||||
private void writeExceptionHandlers(BufWriterImpl buf, int pos, int handlersSize) {
|
||||
for (AbstractPseudoInstruction.ExceptionCatchImpl h : handlers) {
|
||||
int startPc = labelToBci(h.tryStart());
|
||||
int endPc = labelToBci(h.tryEnd());
|
||||
@ -227,6 +227,7 @@ public final class DirectCodeBuilder
|
||||
public void writeBody(BufWriterImpl b) {
|
||||
int pos = b.size();
|
||||
int crSize = characterRangesCount;
|
||||
Util.checkU2(crSize, "character range count");
|
||||
b.writeU2(crSize);
|
||||
for (int i = 0; i < characterRangesCount; i++) {
|
||||
CharacterRange cr = characterRanges[i];
|
||||
@ -262,6 +263,7 @@ public final class DirectCodeBuilder
|
||||
public void writeBody(BufWriterImpl b) {
|
||||
int pos = b.size();
|
||||
int lvSize = localVariablesCount;
|
||||
Util.checkU2(lvSize, "local variable count");
|
||||
b.writeU2(lvSize);
|
||||
for (int i = 0; i < localVariablesCount; i++) {
|
||||
LocalVariable l = localVariables[i];
|
||||
@ -291,6 +293,7 @@ public final class DirectCodeBuilder
|
||||
public void writeBody(BufWriterImpl b) {
|
||||
int pos = b.size();
|
||||
int lvtSize = localVariableTypesCount;
|
||||
Util.checkU2(lvtSize, "local variable type count");
|
||||
b.writeU2(lvtSize);
|
||||
for (int i = 0; i < localVariableTypesCount; i++) {
|
||||
LocalVariableType l = localVariableTypes[i];
|
||||
@ -441,7 +444,7 @@ public final class DirectCodeBuilder
|
||||
b.writeIndex(b.constantPool().utf8Entry(Attributes.NAME_LINE_NUMBER_TABLE));
|
||||
push();
|
||||
b.writeInt(buf.size() + 2);
|
||||
b.writeU2(buf.size() / 4);
|
||||
b.writeU2(Util.checkU2(buf.size() / 4, "line number count"));
|
||||
b.writeBytes(buf);
|
||||
}
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2022, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -35,7 +35,7 @@ public final class InterfacesImpl
|
||||
private final List<ClassEntry> interfaces;
|
||||
|
||||
public InterfacesImpl(List<ClassEntry> interfaces) {
|
||||
this.interfaces = List.copyOf(interfaces);
|
||||
this.interfaces = Util.sanitizeU2List(interfaces);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@ -129,6 +129,7 @@ public final class SplitConstantPool implements ConstantPoolBuilder {
|
||||
if (bsmSize == 0)
|
||||
return false;
|
||||
int pos = buf.size();
|
||||
Util.checkU2(bsmSize, "num bootstrap methods");
|
||||
if (parent != null && parentBsmSize != 0) {
|
||||
parent.writeBootstrapMethods(buf);
|
||||
for (int i = parentBsmSize; i < bsmSize; i++)
|
||||
@ -160,15 +161,14 @@ public final class SplitConstantPool implements ConstantPoolBuilder {
|
||||
|
||||
void writeTo(BufWriterImpl buf) {
|
||||
int writeFrom = 1;
|
||||
if (size() >= 65536) {
|
||||
throw new IllegalArgumentException(String.format("Constant pool is too large %d", size()));
|
||||
}
|
||||
buf.writeU2(size());
|
||||
int mySize = size();
|
||||
Util.checkU2(mySize, "constant pool count");
|
||||
buf.writeU2(mySize);
|
||||
if (parent != null && buf.constantPool().canWriteDirect(this)) {
|
||||
parent.writeConstantPoolEntries(buf);
|
||||
writeFrom = parent.size();
|
||||
}
|
||||
for (int i = writeFrom; i < size(); ) {
|
||||
for (int i = writeFrom; i < mySize; ) {
|
||||
var info = (AbstractPoolEntry) entryByIndex(i);
|
||||
info.writeTo(buf);
|
||||
i += info.width();
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2022, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -303,8 +303,8 @@ public class StackMapDecoder {
|
||||
implements StackMapFrameInfo {
|
||||
public StackMapFrameImpl {
|
||||
requireNonNull(target);
|
||||
locals = List.copyOf(locals);
|
||||
stack = List.copyOf(stack);
|
||||
locals = Util.sanitizeU2List(locals);
|
||||
stack = Util.sanitizeU2List(stack);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -108,7 +108,7 @@ public final class TargetInfoImpl {
|
||||
|
||||
public LocalVarTargetImpl(TargetType targetType, List<LocalVarTargetInfo> table) {
|
||||
this.targetType = checkValid(targetType, TARGET_LOCAL_VARIABLE, TARGET_RESOURCE_VARIABLE);
|
||||
this.table = List.copyOf(table);
|
||||
this.table = Util.sanitizeU2List(table);
|
||||
}
|
||||
@Override
|
||||
public int size() {
|
||||
|
||||
@ -174,7 +174,7 @@ public abstract sealed class UnboundAttribute<T extends Attribute<T>>
|
||||
|
||||
public UnboundExceptionsAttribute(List<ClassEntry> exceptions) {
|
||||
super(Attributes.exceptions());
|
||||
this.exceptions = List.copyOf(exceptions);
|
||||
this.exceptions = Util.sanitizeU2List(exceptions);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -244,7 +244,7 @@ public abstract sealed class UnboundAttribute<T extends Attribute<T>>
|
||||
|
||||
public UnboundStackMapTableAttribute(List<StackMapFrameInfo> entries) {
|
||||
super(Attributes.stackMapTable());
|
||||
this.entries = List.copyOf(entries);
|
||||
this.entries = Util.sanitizeU2List(entries);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -268,7 +268,7 @@ public abstract sealed class UnboundAttribute<T extends Attribute<T>>
|
||||
|
||||
public UnboundInnerClassesAttribute(List<InnerClassInfo> innerClasses) {
|
||||
super(Attributes.innerClasses());
|
||||
this.innerClasses = List.copyOf(innerClasses);
|
||||
this.innerClasses = Util.sanitizeU2List(innerClasses);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -292,7 +292,7 @@ public abstract sealed class UnboundAttribute<T extends Attribute<T>>
|
||||
|
||||
public UnboundRecordAttribute(List<RecordComponentInfo> components) {
|
||||
super(Attributes.record());
|
||||
this.components = List.copyOf(components);
|
||||
this.components = Util.sanitizeU2List(components);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -347,7 +347,7 @@ public abstract sealed class UnboundAttribute<T extends Attribute<T>>
|
||||
|
||||
public UnboundMethodParametersAttribute(List<MethodParameterInfo> parameters) {
|
||||
super(Attributes.methodParameters());
|
||||
this.parameters = List.copyOf(parameters);
|
||||
this.parameters = Util.sanitizeU1List(parameters);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -421,7 +421,7 @@ public abstract sealed class UnboundAttribute<T extends Attribute<T>>
|
||||
public UnboundModuleHashesAttribute(Utf8Entry algorithm, List<ModuleHashInfo> hashes) {
|
||||
super(Attributes.moduleHashes());
|
||||
this.algorithm = requireNonNull(algorithm);
|
||||
this.hashes = List.copyOf(hashes);
|
||||
this.hashes = Util.sanitizeU2List(hashes);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -446,16 +446,16 @@ public abstract sealed class UnboundAttribute<T extends Attribute<T>>
|
||||
|
||||
private static final Utf8Entry NAME = TemporaryConstantPool.INSTANCE.utf8Entry(Attributes.NAME_MODULE_PACKAGES);
|
||||
|
||||
private final Collection<PackageEntry> packages;
|
||||
private final List<PackageEntry> packages;
|
||||
|
||||
public UnboundModulePackagesAttribute(Collection<PackageEntry> packages) {
|
||||
super(Attributes.modulePackages());
|
||||
this.packages = List.copyOf(packages);
|
||||
this.packages = Util.sanitizeU2List(packages);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<PackageEntry> packages() {
|
||||
return List.copyOf(packages);
|
||||
return packages;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -498,7 +498,7 @@ public abstract sealed class UnboundAttribute<T extends Attribute<T>>
|
||||
|
||||
public UnboundPermittedSubclassesAttribute(List<ClassEntry> permittedSubclasses) {
|
||||
super(Attributes.permittedSubclasses());
|
||||
this.permittedSubclasses = List.copyOf(permittedSubclasses);
|
||||
this.permittedSubclasses = Util.sanitizeU2List(permittedSubclasses);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -522,7 +522,7 @@ public abstract sealed class UnboundAttribute<T extends Attribute<T>>
|
||||
|
||||
public UnboundNestMembersAttribute(List<ClassEntry> memberEntries) {
|
||||
super(Attributes.nestMembers());
|
||||
this.memberEntries = List.copyOf(memberEntries);
|
||||
this.memberEntries = Util.sanitizeU2List(memberEntries);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -642,7 +642,7 @@ public abstract sealed class UnboundAttribute<T extends Attribute<T>>
|
||||
|
||||
public UnboundCharacterRangeTableAttribute(List<CharacterRangeInfo> ranges) {
|
||||
super(Attributes.characterRangeTable());
|
||||
this.ranges = List.copyOf(ranges);
|
||||
this.ranges = Util.sanitizeU2List(ranges);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -666,7 +666,7 @@ public abstract sealed class UnboundAttribute<T extends Attribute<T>>
|
||||
|
||||
public UnboundLineNumberTableAttribute(List<LineNumberInfo> lines) {
|
||||
super(Attributes.lineNumberTable());
|
||||
this.lines = List.copyOf(lines);
|
||||
this.lines = Util.sanitizeU2List(lines);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -690,7 +690,7 @@ public abstract sealed class UnboundAttribute<T extends Attribute<T>>
|
||||
|
||||
public UnboundLocalVariableTableAttribute(List<LocalVariableInfo> locals) {
|
||||
super(Attributes.localVariableTable());
|
||||
this.locals = List.copyOf(locals);
|
||||
this.locals = Util.sanitizeU2List(locals);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -714,7 +714,7 @@ public abstract sealed class UnboundAttribute<T extends Attribute<T>>
|
||||
|
||||
public UnboundLocalVariableTypeTableAttribute(List<LocalVariableTypeInfo> locals) {
|
||||
super(Attributes.localVariableTypeTable());
|
||||
this.locals = List.copyOf(locals);
|
||||
this.locals = Util.sanitizeU2List(locals);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -738,7 +738,7 @@ public abstract sealed class UnboundAttribute<T extends Attribute<T>>
|
||||
|
||||
public UnboundRuntimeVisibleAnnotationsAttribute(List<Annotation> elements) {
|
||||
super(Attributes.runtimeVisibleAnnotations());
|
||||
this.elements = List.copyOf(elements);
|
||||
this.elements = Util.sanitizeU2List(elements);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -762,7 +762,7 @@ public abstract sealed class UnboundAttribute<T extends Attribute<T>>
|
||||
|
||||
public UnboundRuntimeInvisibleAnnotationsAttribute(List<Annotation> elements) {
|
||||
super(Attributes.runtimeInvisibleAnnotations());
|
||||
this.elements = List.copyOf(elements);
|
||||
this.elements = Util.sanitizeU2List(elements);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -786,13 +786,7 @@ public abstract sealed class UnboundAttribute<T extends Attribute<T>>
|
||||
|
||||
public UnboundRuntimeVisibleParameterAnnotationsAttribute(List<List<Annotation>> elements) {
|
||||
super(Attributes.runtimeVisibleParameterAnnotations());
|
||||
// deep copy
|
||||
var array = elements.toArray().clone();
|
||||
for (int i = 0; i < array.length; i++) {
|
||||
array[i] = List.copyOf((List<?>) array[i]);
|
||||
}
|
||||
|
||||
this.elements = SharedSecrets.getJavaUtilCollectionAccess().listFromTrustedArray(array);
|
||||
this.elements = Util.sanitizeParameterAnnotations(elements);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -816,13 +810,7 @@ public abstract sealed class UnboundAttribute<T extends Attribute<T>>
|
||||
|
||||
public UnboundRuntimeInvisibleParameterAnnotationsAttribute(List<List<Annotation>> elements) {
|
||||
super(Attributes.runtimeInvisibleParameterAnnotations());
|
||||
// deep copy
|
||||
var array = elements.toArray().clone();
|
||||
for (int i = 0; i < array.length; i++) {
|
||||
array[i] = List.copyOf((List<?>) array[i]);
|
||||
}
|
||||
|
||||
this.elements = SharedSecrets.getJavaUtilCollectionAccess().listFromTrustedArray(array);
|
||||
this.elements = Util.sanitizeParameterAnnotations(elements);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -846,7 +834,7 @@ public abstract sealed class UnboundAttribute<T extends Attribute<T>>
|
||||
|
||||
public UnboundRuntimeVisibleTypeAnnotationsAttribute(List<TypeAnnotation> elements) {
|
||||
super(Attributes.runtimeVisibleTypeAnnotations());
|
||||
this.elements = List.copyOf(elements);
|
||||
this.elements = Util.sanitizeU2List(elements);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -870,7 +858,7 @@ public abstract sealed class UnboundAttribute<T extends Attribute<T>>
|
||||
|
||||
public UnboundRuntimeInvisibleTypeAnnotationsAttribute(List<TypeAnnotation> elements) {
|
||||
super(Attributes.runtimeInvisibleTypeAnnotations());
|
||||
this.elements = List.copyOf(elements);
|
||||
this.elements = Util.sanitizeU2List(elements);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -955,7 +943,7 @@ public abstract sealed class UnboundAttribute<T extends Attribute<T>>
|
||||
public UnboundModuleExportInfo {
|
||||
requireNonNull(exportedPackage);
|
||||
Util.checkFlags(exportsFlagsMask);
|
||||
exportsTo = List.copyOf(exportsTo);
|
||||
exportsTo = Util.sanitizeU2List(exportsTo);
|
||||
}
|
||||
}
|
||||
|
||||
@ -973,7 +961,7 @@ public abstract sealed class UnboundAttribute<T extends Attribute<T>>
|
||||
public UnboundModuleOpenInfo {
|
||||
requireNonNull(openedPackage);
|
||||
Util.checkFlags(opensFlagsMask);
|
||||
opensTo = List.copyOf(opensTo);
|
||||
opensTo = Util.sanitizeU2List(opensTo);
|
||||
}
|
||||
}
|
||||
|
||||
@ -982,7 +970,7 @@ public abstract sealed class UnboundAttribute<T extends Attribute<T>>
|
||||
implements ModuleProvideInfo {
|
||||
public UnboundModuleProvideInfo {
|
||||
requireNonNull(provides);
|
||||
providesWith = List.copyOf(providesWith);
|
||||
providesWith = Util.sanitizeU2List(providesWith);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1003,7 +991,7 @@ public abstract sealed class UnboundAttribute<T extends Attribute<T>>
|
||||
public UnboundRecordComponentInfo {
|
||||
requireNonNull(name);
|
||||
requireNonNull(descriptor);
|
||||
attributes = List.copyOf(attributes);
|
||||
attributes = Util.sanitizeU2List(attributes);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1013,7 +1001,7 @@ public abstract sealed class UnboundAttribute<T extends Attribute<T>>
|
||||
|
||||
public UnboundTypeAnnotation {
|
||||
requireNonNull(targetInfo);
|
||||
targetPath = List.copyOf(targetPath);
|
||||
targetPath = Util.sanitizeU1List(targetPath);
|
||||
requireNonNull(annotation);
|
||||
}
|
||||
}
|
||||
@ -1047,11 +1035,11 @@ public abstract sealed class UnboundAttribute<T extends Attribute<T>>
|
||||
this.moduleName = requireNonNull(moduleName);
|
||||
this.moduleFlags = Util.checkFlags(moduleFlags);
|
||||
this.moduleVersion = moduleVersion;
|
||||
this.requires = List.copyOf(requires);
|
||||
this.exports = List.copyOf(exports);
|
||||
this.opens = List.copyOf(opens);
|
||||
this.uses = List.copyOf(uses);
|
||||
this.provides = List.copyOf(provides);
|
||||
this.requires = Util.sanitizeU2List(requires);
|
||||
this.exports = Util.sanitizeU2List(exports);
|
||||
this.opens = Util.sanitizeU2List(opens);
|
||||
this.uses = Util.sanitizeU2List(uses);
|
||||
this.provides = Util.sanitizeU2List(provides);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@ -146,6 +146,33 @@ public final class Util {
|
||||
: ClassDesc.ofInternalName(classInternalNameOrArrayDesc);
|
||||
}
|
||||
|
||||
/// Sanitizes an input list to make it immutable, and verify its size can
|
||||
/// be represented with U1, throwing IAE otherwise.
|
||||
public static <T> List<T> sanitizeU1List(List<T> input) {
|
||||
var copy = List.copyOf(input);
|
||||
checkU1(copy.size(), "list size");
|
||||
return copy;
|
||||
}
|
||||
|
||||
/// Sanitizes an input list to make it immutable, and verify its size can
|
||||
/// be represented with U2, throwing IAE otherwise.
|
||||
public static <T> List<T> sanitizeU2List(Collection<T> input) {
|
||||
var copy = List.copyOf(input);
|
||||
checkU2(copy.size(), "list size");
|
||||
return copy;
|
||||
}
|
||||
|
||||
/// Sanitizes an input nested list of parameter annotations.
|
||||
public static List<List<Annotation>> sanitizeParameterAnnotations(List<List<Annotation>> input) {
|
||||
var array = input.toArray().clone();
|
||||
checkU1(array.length, "parameter count");
|
||||
for (int i = 0; i < array.length; i++) {
|
||||
array[i] = sanitizeU2List((List<?>) array[i]);
|
||||
}
|
||||
|
||||
return SharedSecrets.getJavaUtilCollectionAccess().listFromTrustedArray(array);
|
||||
}
|
||||
|
||||
public static<T, U> List<U> mappedList(List<? extends T> list, Function<T, U> mapper) {
|
||||
return new AbstractList<>() {
|
||||
@Override
|
||||
@ -259,6 +286,7 @@ public final class Util {
|
||||
@ForceInline
|
||||
public static void writeAttributes(BufWriterImpl buf, List<? extends Attribute<?>> list) {
|
||||
int size = list.size();
|
||||
Util.checkU2(size, "attributes count");
|
||||
buf.writeU2(size);
|
||||
for (int i = 0; i < size; i++) {
|
||||
writeAttribute(buf, list.get(i));
|
||||
@ -267,6 +295,7 @@ public final class Util {
|
||||
|
||||
@ForceInline
|
||||
static void writeList(BufWriterImpl buf, Writable[] array, int size) {
|
||||
Util.checkU2(size, "member count");
|
||||
buf.writeU2(size);
|
||||
for (int i = 0; i < size; i++) {
|
||||
array[i].writeTo(buf);
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2022, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -23,17 +23,22 @@
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8320360 8330684 8331320 8331655 8331940 8332486 8335820 8336833
|
||||
* @bug 8320360 8330684 8331320 8331655 8331940 8332486 8335820 8336833 8361635
|
||||
* @summary Testing ClassFile limits.
|
||||
* @run junit LimitsTest
|
||||
*/
|
||||
|
||||
import java.lang.classfile.AttributeMapper;
|
||||
import java.lang.classfile.AttributedElement;
|
||||
import java.lang.classfile.Attributes;
|
||||
import java.lang.classfile.constantpool.PoolEntry;
|
||||
import java.lang.constant.ClassDesc;
|
||||
import java.lang.constant.ConstantDescs;
|
||||
import java.lang.constant.MethodTypeDesc;
|
||||
import java.lang.classfile.BufWriter;
|
||||
import java.lang.classfile.ClassFile;
|
||||
import java.lang.classfile.ClassReader;
|
||||
import java.lang.classfile.CodeBuilder;
|
||||
import java.lang.classfile.CustomAttribute;
|
||||
import java.lang.classfile.Label;
|
||||
import java.lang.classfile.Opcode;
|
||||
import java.lang.classfile.Signature;
|
||||
import java.lang.classfile.attribute.CodeAttribute;
|
||||
import java.lang.classfile.attribute.LineNumberInfo;
|
||||
import java.lang.classfile.attribute.LineNumberTableAttribute;
|
||||
@ -41,8 +46,16 @@ import java.lang.classfile.attribute.LocalVariableTableAttribute;
|
||||
import java.lang.classfile.constantpool.ConstantPoolBuilder;
|
||||
import java.lang.classfile.constantpool.ConstantPoolException;
|
||||
import java.lang.classfile.constantpool.IntegerEntry;
|
||||
import java.lang.classfile.constantpool.PoolEntry;
|
||||
import java.lang.classfile.constantpool.Utf8Entry;
|
||||
import java.lang.classfile.instruction.SwitchCase;
|
||||
import java.lang.constant.ClassDesc;
|
||||
import java.lang.constant.ConstantDescs;
|
||||
import java.lang.constant.MethodTypeDesc;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.function.BiConsumer;
|
||||
|
||||
import jdk.internal.classfile.impl.BufWriterImpl;
|
||||
import jdk.internal.classfile.impl.DirectCodeBuilder;
|
||||
@ -51,6 +64,8 @@ import jdk.internal.classfile.impl.LabelContext;
|
||||
import jdk.internal.classfile.impl.UnboundAttribute;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static java.lang.classfile.ClassFile.ACC_STATIC;
|
||||
import static java.lang.constant.ConstantDescs.*;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
class LimitsTest {
|
||||
@ -73,6 +88,114 @@ class LimitsTest {
|
||||
}));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testBsmOverLimit() {
|
||||
AtomicBoolean reached = new AtomicBoolean();
|
||||
assertThrows(IllegalArgumentException.class, () -> ClassFile.of().build(CD_Void, clb -> {
|
||||
var cp = clb.constantPool();
|
||||
var mhe = cp.methodHandleEntry(BSM_GET_STATIC_FINAL);
|
||||
var digits = new IntegerEntry[10];
|
||||
for (int i = 0; i < 10; i++) {
|
||||
digits[i] = cp.intEntry(i);
|
||||
}
|
||||
int lastIndex = -1;
|
||||
for (int i = 0; i < 66000; i++) {
|
||||
lastIndex = cp.bsmEntry(mhe, List.of(
|
||||
digits[i / 10000 % 10],
|
||||
digits[i / 1000 % 10],
|
||||
digits[i / 100 % 10],
|
||||
digits[i / 10 % 10],
|
||||
digits[i / 1 % 10])).bsmIndex();
|
||||
}
|
||||
assertEquals(65999, lastIndex);
|
||||
reached.set(true);
|
||||
}));
|
||||
assertTrue(reached.get());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testTooManyFields() {
|
||||
AtomicBoolean reached = new AtomicBoolean();
|
||||
assertThrows(IllegalArgumentException.class, () -> ClassFile.of().build(CD_Void, clb -> {
|
||||
for (int i = 1; i < 66000; i++) {
|
||||
clb.withField("f", CD_int, 0);
|
||||
}
|
||||
reached.set(true);
|
||||
}));
|
||||
assertTrue(reached.get());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testTooManyMethods() {
|
||||
AtomicBoolean reached = new AtomicBoolean();
|
||||
assertThrows(IllegalArgumentException.class, () -> ClassFile.of().build(CD_Void, clb -> {
|
||||
for (int i = 1; i < 66000; i++) {
|
||||
clb.withMethodBody("m", MTD_void, 0, CodeBuilder::return_);
|
||||
}
|
||||
reached.set(true);
|
||||
}));
|
||||
assertTrue(reached.get());
|
||||
}
|
||||
|
||||
static final class MyAttribute extends CustomAttribute<MyAttribute> {
|
||||
static final MyAttribute INSTANCE = new MyAttribute();
|
||||
|
||||
private enum Mapper implements AttributeMapper<MyAttribute> {
|
||||
INSTANCE;
|
||||
|
||||
@Override
|
||||
public MyAttribute readAttribute(AttributedElement enclosing, ClassReader cf, int pos) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeAttribute(BufWriter buf, MyAttribute attr) {
|
||||
buf.writeIndex(buf.constantPool().utf8Entry("MyAttribute"));
|
||||
buf.writeInt(0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean allowMultiple() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AttributeStability stability() {
|
||||
return AttributeStability.STATELESS;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
private MyAttribute() {
|
||||
super(Mapper.INSTANCE);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void testTooManyClassAttributes() {
|
||||
AtomicBoolean reached = new AtomicBoolean();
|
||||
assertThrows(IllegalArgumentException.class, () -> ClassFile.of().build(CD_Void, clb -> {
|
||||
for (int i = 1; i < 66000; i++) {
|
||||
clb.with(MyAttribute.INSTANCE);
|
||||
}
|
||||
reached.set(true);
|
||||
}));
|
||||
assertTrue(reached.get());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testTooManyFieldAttributes() {
|
||||
AtomicBoolean reached = new AtomicBoolean();
|
||||
assertThrows(IllegalArgumentException.class, () -> ClassFile.of().build(CD_Void, clb -> clb.withField("f", CD_int, fb -> {
|
||||
for (int i = 1; i < 66000; i++) {
|
||||
fb.with(MyAttribute.INSTANCE);
|
||||
}
|
||||
reached.set(true);
|
||||
})));
|
||||
assertTrue(reached.get());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testCodeOverLimit() {
|
||||
assertThrows(IllegalArgumentException.class, () -> ClassFile.of().build(ClassDesc.of("BigClass"), cb -> cb.withMethodBody(
|
||||
@ -99,6 +222,91 @@ class LimitsTest {
|
||||
assertThrows(IllegalArgumentException.class, () -> lc.getLabel(10));
|
||||
}
|
||||
|
||||
private static void testPseudoOverflow(BiConsumer<CodeBuilder, Label> handler) {
|
||||
ClassFile cf = ClassFile.of(ClassFile.StackMapsOption.DROP_STACK_MAPS);
|
||||
AtomicBoolean reached = new AtomicBoolean(false);
|
||||
assertDoesNotThrow(() -> cf.build(CD_Void, cb -> cb.withMethodBody("test", MTD_void, ACC_STATIC, cob -> {
|
||||
cob.nop();
|
||||
var label = cob.newLabel();
|
||||
for (int i = 0; i < 65535; i++) {
|
||||
handler.accept(cob, label);
|
||||
}
|
||||
cob.labelBinding(label);
|
||||
cob.return_();
|
||||
reached.set(true);
|
||||
})));
|
||||
assertTrue(reached.get());
|
||||
|
||||
reached.set(false);
|
||||
assertThrows(IllegalArgumentException.class, () -> cf.build(CD_Void, cb -> cb.withMethodBody("test", MTD_void, ACC_STATIC, cob -> {
|
||||
cob.nop();
|
||||
var label = cob.newLabel();
|
||||
for (int i = 0; i < 65536; i++) {
|
||||
handler.accept(cob, label);
|
||||
}
|
||||
cob.labelBinding(label);
|
||||
cob.return_();
|
||||
reached.set(true);
|
||||
})));
|
||||
assertTrue(reached.get());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testExceptionCatchOverflow() {
|
||||
testPseudoOverflow((cob, label) -> cob.exceptionCatch(cob.startLabel(), label, label, CD_Throwable));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testLocalVariableOverflow() {
|
||||
testPseudoOverflow((cob, label) -> cob.localVariable(0, "fake", CD_int, cob.startLabel(), label));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testLocalVariableTypeOverflow() {
|
||||
testPseudoOverflow((cob, label) -> cob.localVariableType(0, "fake", Signature.of(CD_int), cob.startLabel(), label));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testCharacterRangeOverflow() {
|
||||
testPseudoOverflow((cob, label) -> cob.characterRange(cob.startLabel(), label, 0, 0, 0));
|
||||
}
|
||||
|
||||
// LineNumber deduplicates so cannot really overflow
|
||||
|
||||
@Test
|
||||
void testHugeLookupswitch() {
|
||||
assertThrows(IllegalArgumentException.class, () -> ClassFile.of().build(CD_Void, clb -> clb.withMethodBody("test", MTD_void, ACC_STATIC, cob -> {
|
||||
var l = cob.newLabel();
|
||||
// 10000 * 8 > 65535
|
||||
var cases = new ArrayList<SwitchCase>(10000);
|
||||
for (int i = 0; i < 10000; i++) {
|
||||
cases.add(SwitchCase.of(i, l));
|
||||
}
|
||||
cob.lookupswitch(l, cases);
|
||||
cob.labelBinding(l);
|
||||
cob.return_();
|
||||
})));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testHugeTableswitch() {
|
||||
assertThrows(IllegalArgumentException.class, () -> ClassFile.of().build(CD_Void, clb -> clb.withMethodBody("test", MTD_void, ACC_STATIC, cob -> {
|
||||
var l = cob.newLabel();
|
||||
// 20000 * 4 > 65535
|
||||
cob.tableswitch(-10000, 10000, l, List.of());
|
||||
cob.labelBinding(l);
|
||||
cob.return_();
|
||||
})));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testHugeUtf8Entry() {
|
||||
var longString = String.valueOf((char) 0x800).repeat(22000);
|
||||
assertThrows(IllegalArgumentException.class, () -> ClassFile.of().build(CD_Void, clb -> {
|
||||
clb.constantPool().utf8Entry(longString);
|
||||
}));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSupportedClassVersion() {
|
||||
var cf = ClassFile.of();
|
||||
|
||||
348
test/jdk/jdk/classfile/ListValidationTest.java
Normal file
348
test/jdk/jdk/classfile/ListValidationTest.java
Normal file
@ -0,0 +1,348 @@
|
||||
/*
|
||||
* Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8361635
|
||||
* @summary Testing list size validation in class file format.
|
||||
* @run junit ListValidationTest
|
||||
*/
|
||||
|
||||
import java.lang.classfile.Annotation;
|
||||
import java.lang.classfile.AnnotationElement;
|
||||
import java.lang.classfile.AnnotationValue;
|
||||
import java.lang.classfile.ClassFile;
|
||||
import java.lang.classfile.Interfaces;
|
||||
import java.lang.classfile.Label;
|
||||
import java.lang.classfile.TypeAnnotation;
|
||||
import java.lang.classfile.attribute.*;
|
||||
import java.lang.classfile.constantpool.ConstantPoolBuilder;
|
||||
import java.lang.constant.ModuleDesc;
|
||||
import java.lang.constant.PackageDesc;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
import jdk.internal.classfile.impl.TemporaryConstantPool;
|
||||
import jdk.internal.classfile.impl.UnboundAttribute;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static java.lang.constant.ConstantDescs.*;
|
||||
import static java.util.Collections.nCopies;
|
||||
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
|
||||
class ListValidationTest {
|
||||
@Test
|
||||
void testAnnotationElements() {
|
||||
var e = AnnotationElement.ofInt("dummy", 0);
|
||||
assertDoesNotThrow(() -> Annotation.of(CD_String, nCopies(65535, e)));
|
||||
assertThrows(IllegalArgumentException.class, () -> Annotation.of(CD_String, nCopies(66000, e)));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testAnnotationArrayValue() {
|
||||
var v = AnnotationValue.ofInt(0);
|
||||
assertDoesNotThrow(() -> AnnotationValue.ofArray(nCopies(65535, v)));
|
||||
assertThrows(IllegalArgumentException.class, () -> AnnotationValue.ofArray(nCopies(66000, v)));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testTypeAnnotationPath() {
|
||||
var anno = Annotation.of(CD_String);
|
||||
assertDoesNotThrow(() -> TypeAnnotation.of(TypeAnnotation.TargetInfo.ofField(), nCopies(255, TypeAnnotation.TypePathComponent.INNER_TYPE), anno));
|
||||
assertThrows(IllegalArgumentException.class, () -> TypeAnnotation.of(TypeAnnotation.TargetInfo.ofField(), nCopies(256, TypeAnnotation.TypePathComponent.INNER_TYPE), anno));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testBsmArgs() {
|
||||
var cpb = ConstantPoolBuilder.of();
|
||||
assertDoesNotThrow(() -> cpb.bsmEntry(BSM_INVOKE, nCopies(65535, 0)));
|
||||
assertThrows(IllegalArgumentException.class, () -> cpb.bsmEntry(BSM_INVOKE, nCopies(66000, 0)));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testInterfaces() {
|
||||
var cpb = ConstantPoolBuilder.of();
|
||||
assertDoesNotThrow(() -> Interfaces.ofSymbols(nCopies(65535, CD_Number)));
|
||||
assertThrows(IllegalArgumentException.class, () -> cpb.bsmEntry(BSM_INVOKE, nCopies(66000, 0)));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testStackMapFrame() {
|
||||
Label label = dummyLabel();
|
||||
assertDoesNotThrow(() -> StackMapFrameInfo.of(label,
|
||||
nCopies(65535, StackMapFrameInfo.SimpleVerificationTypeInfo.INTEGER),
|
||||
nCopies(65535, StackMapFrameInfo.SimpleVerificationTypeInfo.DOUBLE)));
|
||||
assertThrows(IllegalArgumentException.class, () -> StackMapFrameInfo.of(label,
|
||||
nCopies(66000, StackMapFrameInfo.SimpleVerificationTypeInfo.INTEGER),
|
||||
nCopies(65535, StackMapFrameInfo.SimpleVerificationTypeInfo.DOUBLE)));
|
||||
assertThrows(IllegalArgumentException.class, () -> StackMapFrameInfo.of(label,
|
||||
nCopies(65535, StackMapFrameInfo.SimpleVerificationTypeInfo.INTEGER),
|
||||
nCopies(66000, StackMapFrameInfo.SimpleVerificationTypeInfo.DOUBLE)));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testTypeAnnotationLocalVarTarget() {
|
||||
Label label = dummyLabel();
|
||||
assertDoesNotThrow(() -> TypeAnnotation.TargetInfo.ofLocalVariable(nCopies(65535, TypeAnnotation.LocalVarTargetInfo.of(label, label, 0))));
|
||||
assertThrows(IllegalArgumentException.class, () -> TypeAnnotation.TargetInfo.ofLocalVariable(nCopies(66000, TypeAnnotation.LocalVarTargetInfo.of(label, label, 0))));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testExceptionsAttribute() {
|
||||
assertDoesNotThrow(() -> ExceptionsAttribute.ofSymbols(nCopies(65535, CD_Throwable)));
|
||||
assertThrows(IllegalArgumentException.class, () -> ExceptionsAttribute.ofSymbols(nCopies(66000, CD_Throwable)));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testStackMapTableAttribute() {
|
||||
var frame = StackMapFrameInfo.of(dummyLabel(),
|
||||
nCopies(65535, StackMapFrameInfo.SimpleVerificationTypeInfo.INTEGER),
|
||||
nCopies(65535, StackMapFrameInfo.SimpleVerificationTypeInfo.DOUBLE));
|
||||
assertDoesNotThrow(() -> StackMapTableAttribute.of(nCopies(65535, frame)));
|
||||
assertThrows(IllegalArgumentException.class, () -> StackMapTableAttribute.of(nCopies(66000, frame)));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testInnerClassesAttribute() {
|
||||
var entry = InnerClassInfo.of(CD_Void, Optional.empty(), Optional.empty(), 0);
|
||||
assertDoesNotThrow(() -> InnerClassesAttribute.of(nCopies(65535, entry)));
|
||||
assertThrows(IllegalArgumentException.class, () -> InnerClassesAttribute.of(nCopies(66000, entry)));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testRecordAttribute() {
|
||||
var component = RecordComponentInfo.of("hello", CD_int, List.of());
|
||||
assertDoesNotThrow(() -> RecordAttribute.of(nCopies(65535, component)));
|
||||
assertThrows(IllegalArgumentException.class, () -> RecordAttribute.of(nCopies(66000, component)));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testMethodParametersAttribute() {
|
||||
var component = MethodParameterInfo.of(Optional.empty(), 0);
|
||||
assertDoesNotThrow(() -> MethodParametersAttribute.of(nCopies(255, component)));
|
||||
assertThrows(IllegalArgumentException.class, () -> MethodParametersAttribute.of(nCopies(300, component)));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testModuleHashesAttribute() {
|
||||
var hash = ModuleHashInfo.of(ModuleDesc.of("java.base"), new byte[0]);
|
||||
assertDoesNotThrow(() -> ModuleHashesAttribute.of("dummy", nCopies(65535, hash)));
|
||||
assertThrows(IllegalArgumentException.class, () -> ModuleHashesAttribute.of("dummy", nCopies(66000, hash)));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testModulePackagesAttribute() {
|
||||
var pkgDesc = PackageDesc.of("java.io");
|
||||
assertDoesNotThrow(() -> ModulePackagesAttribute.ofNames(nCopies(65535, pkgDesc)));
|
||||
assertThrows(IllegalArgumentException.class, () -> ModulePackagesAttribute.ofNames(nCopies(66000, pkgDesc)));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testPermittedSubclassesAttribute() {
|
||||
assertDoesNotThrow(() -> PermittedSubclassesAttribute.ofSymbols(nCopies(65535, CD_Collection)));
|
||||
assertThrows(IllegalArgumentException.class, () -> PermittedSubclassesAttribute.ofSymbols(nCopies(66000, CD_Collection)));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testNestMembersAttribute() {
|
||||
assertDoesNotThrow(() -> NestMembersAttribute.ofSymbols(nCopies(65535, CD_Collection)));
|
||||
assertThrows(IllegalArgumentException.class, () -> NestMembersAttribute.ofSymbols(nCopies(66000, CD_Collection)));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testCharacterRangeTableAttribute() {
|
||||
var range = CharacterRangeInfo.of(0, 0, 0, 0, 0);
|
||||
assertDoesNotThrow(() -> CharacterRangeTableAttribute.of(nCopies(65535, range)));
|
||||
assertThrows(IllegalArgumentException.class, () -> CharacterRangeTableAttribute.of(nCopies(66000, range)));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testLineNumberTableAttribute() {
|
||||
var lineNumber = LineNumberInfo.of(0, 0);
|
||||
assertDoesNotThrow(() -> LineNumberTableAttribute.of(nCopies(65535, lineNumber)));
|
||||
assertThrows(IllegalArgumentException.class, () -> LineNumberTableAttribute.of(nCopies(66000, lineNumber)));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testLocalVariableTableAttribute() {
|
||||
var utf8 = TemporaryConstantPool.INSTANCE.utf8Entry("dummy");
|
||||
var localVariable = new UnboundAttribute.UnboundLocalVariableInfo(0, 0, utf8, utf8, 0);
|
||||
assertDoesNotThrow(() -> LocalVariableTableAttribute.of(nCopies(65535, localVariable)));
|
||||
assertThrows(IllegalArgumentException.class, () -> LocalVariableTableAttribute.of(nCopies(66000, localVariable)));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testLocalVariableTypeTableAttribute() {
|
||||
var utf8 = TemporaryConstantPool.INSTANCE.utf8Entry("dummy");
|
||||
var localVariableType = new UnboundAttribute.UnboundLocalVariableTypeInfo(0, 0, utf8, utf8, 0);
|
||||
assertDoesNotThrow(() -> LocalVariableTypeTableAttribute.of(nCopies(65535, localVariableType)));
|
||||
assertThrows(IllegalArgumentException.class, () -> LocalVariableTypeTableAttribute.of(nCopies(66000, localVariableType)));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testRuntimeVisibleAnnotationsAttribute() {
|
||||
var anno = Annotation.of(CD_String);
|
||||
assertDoesNotThrow(() -> RuntimeVisibleAnnotationsAttribute.of(nCopies(65535, anno)));
|
||||
assertThrows(IllegalArgumentException.class, () -> RuntimeVisibleAnnotationsAttribute.of(nCopies(66000, anno)));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testRuntimeInvisibleAnnotationsAttribute() {
|
||||
var anno = Annotation.of(CD_String);
|
||||
assertDoesNotThrow(() -> RuntimeInvisibleAnnotationsAttribute.of(nCopies(65535, anno)));
|
||||
assertThrows(IllegalArgumentException.class, () -> RuntimeInvisibleAnnotationsAttribute.of(nCopies(66000, anno)));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testRuntimeVisibleParameterAnnotationsAttributeTopLevel() {
|
||||
assertDoesNotThrow(() -> RuntimeVisibleParameterAnnotationsAttribute.of(nCopies(255, List.of())));
|
||||
assertThrows(IllegalArgumentException.class, () -> RuntimeVisibleParameterAnnotationsAttribute.of(nCopies(256, List.of())));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testRuntimeInvisibleParameterAnnotationsAttributeTopLevel() {
|
||||
assertDoesNotThrow(() -> RuntimeInvisibleParameterAnnotationsAttribute.of(nCopies(255, List.of())));
|
||||
assertThrows(IllegalArgumentException.class, () -> RuntimeInvisibleParameterAnnotationsAttribute.of(nCopies(256, List.of())));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testRuntimeVisibleParameterAnnotationsAttributeNested() {
|
||||
var anno = Annotation.of(CD_String);
|
||||
assertDoesNotThrow(() -> RuntimeVisibleParameterAnnotationsAttribute.of(List.of(nCopies(65535, anno))));
|
||||
assertThrows(IllegalArgumentException.class, () -> RuntimeVisibleParameterAnnotationsAttribute.of(List.of(nCopies(65536, anno))));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testRuntimeInvisibleParameterAnnotationsAttributeNested() {
|
||||
var anno = Annotation.of(CD_String);
|
||||
assertDoesNotThrow(() -> RuntimeInvisibleParameterAnnotationsAttribute.of(List.of(nCopies(65535, anno))));
|
||||
assertThrows(IllegalArgumentException.class, () -> RuntimeInvisibleParameterAnnotationsAttribute.of(List.of(nCopies(65536, anno))));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testRuntimeVisibleTypeAnnotationsAttribute() {
|
||||
var anno = TypeAnnotation.of(TypeAnnotation.TargetInfo.ofMethodReturn(), List.of(), Annotation.of(CD_String));
|
||||
assertDoesNotThrow(() -> RuntimeVisibleTypeAnnotationsAttribute.of(nCopies(65535, anno)));
|
||||
assertThrows(IllegalArgumentException.class, () -> RuntimeVisibleTypeAnnotationsAttribute.of(nCopies(66000, anno)));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testRuntimeInvisibleTypeAnnotationsAttribute() {
|
||||
var anno = TypeAnnotation.of(TypeAnnotation.TargetInfo.ofMethodReturn(), List.of(), Annotation.of(CD_String));
|
||||
assertDoesNotThrow(() -> RuntimeInvisibleTypeAnnotationsAttribute.of(nCopies(65535, anno)));
|
||||
assertThrows(IllegalArgumentException.class, () -> RuntimeInvisibleTypeAnnotationsAttribute.of(nCopies(66000, anno)));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testModuleExportEntry() {
|
||||
var pkg = PackageDesc.of("dummy.test");
|
||||
var mod = ModuleDesc.of("the.other");
|
||||
assertDoesNotThrow(() -> ModuleExportInfo.of(pkg, 0, nCopies(65535, mod)));
|
||||
assertThrows(IllegalArgumentException.class, () -> ModuleExportInfo.of(pkg, 0, nCopies(66000, mod)));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testModuleOpenEntry() {
|
||||
var pkg = PackageDesc.of("dummy.test");
|
||||
var mod = ModuleDesc.of("the.other");
|
||||
assertDoesNotThrow(() -> ModuleOpenInfo.of(pkg, 0, nCopies(65535, mod)));
|
||||
assertThrows(IllegalArgumentException.class, () -> ModuleOpenInfo.of(pkg, 0, nCopies(66000, mod)));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testModuleProvideEntry() {
|
||||
assertDoesNotThrow(() -> ModuleProvideInfo.of(CD_Object, nCopies(65535, CD_String)));
|
||||
assertThrows(IllegalArgumentException.class, () -> ModuleProvideInfo.of(CD_Object, nCopies(66000, CD_String)));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testRecordComponentAttributes() {
|
||||
var attr = SyntheticAttribute.of();
|
||||
assertDoesNotThrow(() -> RecordComponentInfo.of("dummy", CD_int, nCopies(65535, attr)));
|
||||
assertThrows(IllegalArgumentException.class, () -> RecordComponentInfo.of("dummy", CD_int, nCopies(66000, attr)));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testModuleAttribute() {
|
||||
var md = ModuleDesc.of("java.base");
|
||||
var pkg = PackageDesc.of("java.lang");
|
||||
var require = ModuleRequireInfo.of(md, 0, null);
|
||||
var export = ModuleExportInfo.of(pkg, 0, List.of());
|
||||
var provide = ModuleProvideInfo.of(CD_Object, List.of());
|
||||
var open = ModuleOpenInfo.of(pkg, 0, List.of());
|
||||
var classEntry = TemporaryConstantPool.INSTANCE.classEntry(CD_String);
|
||||
var moduleEntry = TemporaryConstantPool.INSTANCE.moduleEntry(md);
|
||||
assertDoesNotThrow(() -> ModuleAttribute.of(moduleEntry, 0, null,
|
||||
nCopies(65535, require),
|
||||
nCopies(65535, export),
|
||||
nCopies(65535, open),
|
||||
nCopies(65535, classEntry),
|
||||
nCopies(65535, provide)
|
||||
));
|
||||
assertThrows(IllegalArgumentException.class, () -> ModuleAttribute.of(moduleEntry, 0, null,
|
||||
nCopies(66000, require),
|
||||
nCopies(65535, export),
|
||||
nCopies(65535, open),
|
||||
nCopies(65535, classEntry),
|
||||
nCopies(65535, provide)
|
||||
));
|
||||
assertThrows(IllegalArgumentException.class, () -> ModuleAttribute.of(moduleEntry, 0, null,
|
||||
nCopies(65535, require),
|
||||
nCopies(66000, export),
|
||||
nCopies(65535, open),
|
||||
nCopies(65535, classEntry),
|
||||
nCopies(65535, provide)
|
||||
));
|
||||
assertThrows(IllegalArgumentException.class, () -> ModuleAttribute.of(moduleEntry, 0, null,
|
||||
nCopies(65535, require),
|
||||
nCopies(65535, export),
|
||||
nCopies(66000, open),
|
||||
nCopies(65535, classEntry),
|
||||
nCopies(65535, provide)
|
||||
));
|
||||
assertThrows(IllegalArgumentException.class, () -> ModuleAttribute.of(moduleEntry, 0, null,
|
||||
nCopies(65535, require),
|
||||
nCopies(65535, export),
|
||||
nCopies(65535, open),
|
||||
nCopies(66000, classEntry),
|
||||
nCopies(65535, provide)
|
||||
));
|
||||
assertThrows(IllegalArgumentException.class, () -> ModuleAttribute.of(moduleEntry, 0, null,
|
||||
nCopies(65535, require),
|
||||
nCopies(65535, export),
|
||||
nCopies(65535, open),
|
||||
nCopies(65535, classEntry),
|
||||
nCopies(66000, provide)
|
||||
));
|
||||
}
|
||||
|
||||
private static Label dummyLabel() {
|
||||
Label[] capture = new Label[1];
|
||||
ClassFile.of().build(CD_Object, clb -> clb.withMethodBody("test", MTD_void, 0, cob -> {
|
||||
capture[0] = cob.startLabel();
|
||||
cob.return_();
|
||||
}));
|
||||
return capture[0];
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user