mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-26 14:24:46 +02:00
8317356: Fix missing null checks in the ClassFile API
Co-authored-by: Nizar Benalla <nbenalla@openjdk.org> Reviewed-by: asotona
This commit is contained in:
parent
60713463c7
commit
a2c775222e
36 changed files with 249 additions and 116 deletions
|
@ -42,6 +42,8 @@ import java.util.List;
|
|||
import jdk.internal.classfile.impl.Util;
|
||||
import jdk.internal.javac.PreviewFeature;
|
||||
|
||||
import static java.util.Objects.requireNonNull;
|
||||
|
||||
/**
|
||||
* Models an {@code element_value} structure, or a value of an element-value
|
||||
* pair of an annotation, as defined in JVMS {@jvms 4.7.16.1}.
|
||||
|
@ -488,6 +490,8 @@ public sealed interface AnnotationValue {
|
|||
*/
|
||||
static OfEnum ofEnum(Utf8Entry className,
|
||||
Utf8Entry constantName) {
|
||||
requireNonNull(className);
|
||||
requireNonNull(constantName);
|
||||
return new AnnotationImpl.OfEnumImpl(className, constantName);
|
||||
}
|
||||
|
||||
|
@ -506,6 +510,7 @@ public sealed interface AnnotationValue {
|
|||
* @param className the descriptor string of the class
|
||||
*/
|
||||
static OfClass ofClass(Utf8Entry className) {
|
||||
requireNonNull(className);
|
||||
return new AnnotationImpl.OfClassImpl(className);
|
||||
}
|
||||
|
||||
|
@ -522,6 +527,7 @@ public sealed interface AnnotationValue {
|
|||
* @param value the string
|
||||
*/
|
||||
static OfString ofString(Utf8Entry value) {
|
||||
requireNonNull(value);
|
||||
return new AnnotationImpl.OfStringImpl(value);
|
||||
}
|
||||
|
||||
|
@ -538,6 +544,7 @@ public sealed interface AnnotationValue {
|
|||
* @param value the double value
|
||||
*/
|
||||
static OfDouble ofDouble(DoubleEntry value) {
|
||||
requireNonNull(value);
|
||||
return new AnnotationImpl.OfDoubleImpl(value);
|
||||
}
|
||||
|
||||
|
@ -554,6 +561,7 @@ public sealed interface AnnotationValue {
|
|||
* @param value the float value
|
||||
*/
|
||||
static OfFloat ofFloat(FloatEntry value) {
|
||||
requireNonNull(value);
|
||||
return new AnnotationImpl.OfFloatImpl(value);
|
||||
}
|
||||
|
||||
|
@ -570,6 +578,7 @@ public sealed interface AnnotationValue {
|
|||
* @param value the long value
|
||||
*/
|
||||
static OfLong ofLong(LongEntry value) {
|
||||
requireNonNull(value);
|
||||
return new AnnotationImpl.OfLongImpl(value);
|
||||
}
|
||||
|
||||
|
@ -586,6 +595,7 @@ public sealed interface AnnotationValue {
|
|||
* @param value the int value
|
||||
*/
|
||||
static OfInt ofInt(IntegerEntry value) {
|
||||
requireNonNull(value);
|
||||
return new AnnotationImpl.OfIntImpl(value);
|
||||
}
|
||||
|
||||
|
@ -602,6 +612,7 @@ public sealed interface AnnotationValue {
|
|||
* @param value the short value
|
||||
*/
|
||||
static OfShort ofShort(IntegerEntry value) {
|
||||
requireNonNull(value);
|
||||
return new AnnotationImpl.OfShortImpl(value);
|
||||
}
|
||||
|
||||
|
@ -618,6 +629,7 @@ public sealed interface AnnotationValue {
|
|||
* @param value the char value
|
||||
*/
|
||||
static OfChar ofChar(IntegerEntry value) {
|
||||
requireNonNull(value);
|
||||
return new AnnotationImpl.OfCharImpl(value);
|
||||
}
|
||||
|
||||
|
@ -634,6 +646,7 @@ public sealed interface AnnotationValue {
|
|||
* @param value the byte value
|
||||
*/
|
||||
static OfByte ofByte(IntegerEntry value) {
|
||||
requireNonNull(value);
|
||||
return new AnnotationImpl.OfByteImpl(value);
|
||||
}
|
||||
|
||||
|
@ -650,6 +663,7 @@ public sealed interface AnnotationValue {
|
|||
* @param value the boolean value
|
||||
*/
|
||||
static OfBoolean ofBoolean(IntegerEntry value) {
|
||||
requireNonNull(value);
|
||||
return new AnnotationImpl.OfBooleanImpl(value);
|
||||
}
|
||||
|
||||
|
@ -667,6 +681,7 @@ public sealed interface AnnotationValue {
|
|||
* @param value the annotation
|
||||
*/
|
||||
static OfAnnotation ofAnnotation(Annotation value) {
|
||||
requireNonNull(value);
|
||||
return new AnnotationImpl.OfAnnotationImpl(value);
|
||||
}
|
||||
|
||||
|
@ -784,6 +799,6 @@ public sealed interface AnnotationValue {
|
|||
} else if (value instanceof Enum<?> e) {
|
||||
return ofEnum(ClassDesc.ofDescriptor(e.getDeclaringClass().descriptorString()), e.name());
|
||||
}
|
||||
throw new IllegalArgumentException("Illegal annotation constant value type " + (value == null ? null : value.getClass()));
|
||||
throw new IllegalArgumentException("Illegal annotation constant value type " + requireNonNull(value).getClass());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -33,6 +33,8 @@ import java.lang.classfile.attribute.RecordComponentInfo;
|
|||
import jdk.internal.classfile.impl.AbstractUnboundModel;
|
||||
import jdk.internal.javac.PreviewFeature;
|
||||
|
||||
import static java.util.Objects.requireNonNull;
|
||||
|
||||
/**
|
||||
* A {@link ClassFileElement} describing an entity that has attributes, such
|
||||
* as a class, field, method, code attribute, or record component.
|
||||
|
@ -58,6 +60,7 @@ public sealed interface AttributedElement extends ClassFileElement
|
|||
* is not present
|
||||
*/
|
||||
default <T extends Attribute<T>> Optional<T> findAttribute(AttributeMapper<T> attr) {
|
||||
requireNonNull(attr);
|
||||
for (Attribute<?> la : attributes()) {
|
||||
if (la.attributeMapper() == attr) {
|
||||
@SuppressWarnings("unchecked")
|
||||
|
@ -76,6 +79,7 @@ public sealed interface AttributedElement extends ClassFileElement
|
|||
* is not present
|
||||
*/
|
||||
default <T extends Attribute<T>> List<T> findAttributes(AttributeMapper<T> attr) {
|
||||
requireNonNull(attr);
|
||||
var list = new ArrayList<T>();
|
||||
for (var a : attributes()) {
|
||||
if (a.attributeMapper() == attr) {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2022, 2023, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2022, 2024, 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
|
||||
|
@ -39,6 +39,8 @@ import jdk.internal.classfile.impl.ClassHierarchyImpl.StaticClassHierarchyResolv
|
|||
import jdk.internal.classfile.impl.Util;
|
||||
|
||||
import static java.lang.constant.ConstantDescs.CD_Object;
|
||||
import static java.util.Objects.requireNonNull;
|
||||
|
||||
import jdk.internal.javac.PreviewFeature;
|
||||
|
||||
/**
|
||||
|
@ -106,6 +108,7 @@ public interface ClassHierarchyResolver {
|
|||
* other resolver in cases where this resolver returns {@code null}.
|
||||
*/
|
||||
default ClassHierarchyResolver orElse(ClassHierarchyResolver other) {
|
||||
requireNonNull(other);
|
||||
return new ClassHierarchyResolver() {
|
||||
@Override
|
||||
public ClassHierarchyInfo getClassInfo(ClassDesc classDesc) {
|
||||
|
@ -170,7 +173,7 @@ public interface ClassHierarchyResolver {
|
|||
* @return the {@linkplain ClassHierarchyResolver}
|
||||
*/
|
||||
static ClassHierarchyResolver ofResourceParsing(Function<ClassDesc, InputStream> classStreamResolver) {
|
||||
return new ClassHierarchyImpl.ResourceParsingClassHierarchyResolver(classStreamResolver);
|
||||
return new ClassHierarchyImpl.ResourceParsingClassHierarchyResolver(requireNonNull(classStreamResolver));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -181,6 +184,7 @@ public interface ClassHierarchyResolver {
|
|||
* @return the {@linkplain ClassHierarchyResolver}
|
||||
*/
|
||||
static ClassHierarchyResolver ofResourceParsing(ClassLoader loader) {
|
||||
requireNonNull(loader);
|
||||
return ofResourceParsing(new Function<>() {
|
||||
@Override
|
||||
public InputStream apply(ClassDesc classDesc) {
|
||||
|
@ -210,6 +214,7 @@ public interface ClassHierarchyResolver {
|
|||
* @return the class hierarchy resolver
|
||||
*/
|
||||
static ClassHierarchyResolver ofClassLoading(ClassLoader loader) {
|
||||
requireNonNull(loader);
|
||||
return new ClassLoadingClassHierarchyResolver(new Function<>() {
|
||||
@Override
|
||||
public Class<?> apply(ClassDesc cd) {
|
||||
|
@ -232,6 +237,7 @@ public interface ClassHierarchyResolver {
|
|||
* @return the class hierarchy resolver
|
||||
*/
|
||||
static ClassHierarchyResolver ofClassLoading(MethodHandles.Lookup lookup) {
|
||||
requireNonNull(lookup);
|
||||
return new ClassLoadingClassHierarchyResolver(new Function<>() {
|
||||
@Override
|
||||
public Class<?> apply(ClassDesc cd) {
|
||||
|
|
|
@ -32,6 +32,8 @@ import java.lang.classfile.attribute.CodeAttribute;
|
|||
import jdk.internal.classfile.impl.TransformImpl;
|
||||
import jdk.internal.javac.PreviewFeature;
|
||||
|
||||
import static java.util.Objects.requireNonNull;
|
||||
|
||||
/**
|
||||
* A transformation on streams of {@link ClassElement}.
|
||||
*
|
||||
|
@ -63,7 +65,7 @@ public non-sealed interface ClassTransform
|
|||
* @return the stateful class transform
|
||||
*/
|
||||
static ClassTransform ofStateful(Supplier<ClassTransform> supplier) {
|
||||
return new TransformImpl.SupplierClassTransform(supplier);
|
||||
return new TransformImpl.SupplierClassTransform(requireNonNull(supplier));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -74,6 +76,7 @@ public non-sealed interface ClassTransform
|
|||
* @return the class transform
|
||||
*/
|
||||
static ClassTransform endHandler(Consumer<ClassBuilder> finisher) {
|
||||
requireNonNull(finisher);
|
||||
return new ClassTransform() {
|
||||
@Override
|
||||
public void accept(ClassBuilder builder, ClassElement element) {
|
||||
|
@ -95,6 +98,7 @@ public non-sealed interface ClassTransform
|
|||
* @return the class transform
|
||||
*/
|
||||
static ClassTransform dropping(Predicate<ClassElement> filter) {
|
||||
requireNonNull(filter);
|
||||
return (b, e) -> {
|
||||
if (!filter.test(e))
|
||||
b.with(e);
|
||||
|
@ -111,7 +115,7 @@ public non-sealed interface ClassTransform
|
|||
*/
|
||||
static ClassTransform transformingMethods(Predicate<MethodModel> filter,
|
||||
MethodTransform xform) {
|
||||
return new TransformImpl.ClassMethodTransform(xform, filter);
|
||||
return new TransformImpl.ClassMethodTransform(requireNonNull(xform), requireNonNull(filter));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -122,7 +126,7 @@ public non-sealed interface ClassTransform
|
|||
* @return the class transform
|
||||
*/
|
||||
static ClassTransform transformingMethods(MethodTransform xform) {
|
||||
return transformingMethods(mm -> true, xform);
|
||||
return transformingMethods(_ -> true, xform);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -157,7 +161,7 @@ public non-sealed interface ClassTransform
|
|||
* @return the class transform
|
||||
*/
|
||||
static ClassTransform transformingFields(FieldTransform xform) {
|
||||
return new TransformImpl.ClassFieldTransform(xform, f -> true);
|
||||
return new TransformImpl.ClassFieldTransform(requireNonNull(xform), _ -> true);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -169,6 +173,6 @@ public non-sealed interface ClassTransform
|
|||
*/
|
||||
@Override
|
||||
default ClassTransform andThen(ClassTransform t) {
|
||||
return new TransformImpl.ChainedClassTransform(this, t);
|
||||
return new TransformImpl.ChainedClassTransform(this, requireNonNull(t));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -30,6 +30,8 @@ import java.util.function.Supplier;
|
|||
import jdk.internal.classfile.impl.TransformImpl;
|
||||
import jdk.internal.javac.PreviewFeature;
|
||||
|
||||
import static java.util.Objects.requireNonNull;
|
||||
|
||||
/**
|
||||
* A transformation on streams of {@link CodeElement}.
|
||||
*
|
||||
|
@ -61,7 +63,7 @@ public non-sealed interface CodeTransform
|
|||
* @return the stateful code transform
|
||||
*/
|
||||
static CodeTransform ofStateful(Supplier<CodeTransform> supplier) {
|
||||
return new TransformImpl.SupplierCodeTransform(supplier);
|
||||
return new TransformImpl.SupplierCodeTransform(requireNonNull(supplier));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -72,6 +74,7 @@ public non-sealed interface CodeTransform
|
|||
* @return the code transform
|
||||
*/
|
||||
static CodeTransform endHandler(Consumer<CodeBuilder> finisher) {
|
||||
requireNonNull(finisher);
|
||||
return new CodeTransform() {
|
||||
@Override
|
||||
public void accept(CodeBuilder builder, CodeElement element) {
|
||||
|
@ -94,6 +97,6 @@ public non-sealed interface CodeTransform
|
|||
*/
|
||||
@Override
|
||||
default CodeTransform andThen(CodeTransform t) {
|
||||
return new TransformImpl.ChainedCodeTransform(this, t);
|
||||
return new TransformImpl.ChainedCodeTransform(this, requireNonNull(t));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -31,6 +31,8 @@ import java.util.function.Supplier;
|
|||
import jdk.internal.classfile.impl.TransformImpl;
|
||||
import jdk.internal.javac.PreviewFeature;
|
||||
|
||||
import static java.util.Objects.requireNonNull;
|
||||
|
||||
/**
|
||||
* A transformation on streams of {@link FieldElement}.
|
||||
*
|
||||
|
@ -62,7 +64,7 @@ public non-sealed interface FieldTransform
|
|||
* @return the stateful field transform
|
||||
*/
|
||||
static FieldTransform ofStateful(Supplier<FieldTransform> supplier) {
|
||||
return new TransformImpl.SupplierFieldTransform(supplier);
|
||||
return new TransformImpl.SupplierFieldTransform(requireNonNull(supplier));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -73,6 +75,7 @@ public non-sealed interface FieldTransform
|
|||
* @return the field transform
|
||||
*/
|
||||
static FieldTransform endHandler(Consumer<FieldBuilder> finisher) {
|
||||
requireNonNull(finisher);
|
||||
return new FieldTransform() {
|
||||
@Override
|
||||
public void accept(FieldBuilder builder, FieldElement element) {
|
||||
|
@ -94,6 +97,7 @@ public non-sealed interface FieldTransform
|
|||
* @return the field transform
|
||||
*/
|
||||
static FieldTransform dropping(Predicate<FieldElement> filter) {
|
||||
requireNonNull(filter);
|
||||
return (b, e) -> {
|
||||
if (!filter.test(e))
|
||||
b.with(e);
|
||||
|
@ -109,6 +113,6 @@ public non-sealed interface FieldTransform
|
|||
*/
|
||||
@Override
|
||||
default FieldTransform andThen(FieldTransform t) {
|
||||
return new TransformImpl.ChainedFieldTransform(this, t);
|
||||
return new TransformImpl.ChainedFieldTransform(this, requireNonNull(t));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -31,6 +31,8 @@ import java.util.function.Supplier;
|
|||
import jdk.internal.classfile.impl.TransformImpl;
|
||||
import jdk.internal.javac.PreviewFeature;
|
||||
|
||||
import static java.util.Objects.requireNonNull;
|
||||
|
||||
/**
|
||||
* A transformation on streams of {@link MethodElement}.
|
||||
*
|
||||
|
@ -62,6 +64,7 @@ public non-sealed interface MethodTransform
|
|||
* @return the stateful method transform
|
||||
*/
|
||||
static MethodTransform ofStateful(Supplier<MethodTransform> supplier) {
|
||||
requireNonNull(supplier);
|
||||
return new TransformImpl.SupplierMethodTransform(supplier);
|
||||
}
|
||||
|
||||
|
@ -73,6 +76,7 @@ public non-sealed interface MethodTransform
|
|||
* @return the method transform
|
||||
*/
|
||||
static MethodTransform endHandler(Consumer<MethodBuilder> finisher) {
|
||||
requireNonNull(finisher);
|
||||
return new MethodTransform() {
|
||||
@Override
|
||||
public void accept(MethodBuilder builder, MethodElement element) {
|
||||
|
@ -94,6 +98,7 @@ public non-sealed interface MethodTransform
|
|||
* @return the method transform
|
||||
*/
|
||||
static MethodTransform dropping(Predicate<MethodElement> filter) {
|
||||
requireNonNull(filter);
|
||||
return (b, e) -> {
|
||||
if (!filter.test(e))
|
||||
b.with(e);
|
||||
|
@ -108,7 +113,7 @@ public non-sealed interface MethodTransform
|
|||
* @return the class transform
|
||||
*/
|
||||
static MethodTransform transformingCode(CodeTransform xform) {
|
||||
return new TransformImpl.MethodCodeTransform(xform);
|
||||
return new TransformImpl.MethodCodeTransform(requireNonNull(xform));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -120,6 +125,6 @@ public non-sealed interface MethodTransform
|
|||
*/
|
||||
@Override
|
||||
default MethodTransform andThen(MethodTransform t) {
|
||||
return new TransformImpl.ChainedMethodTransform(this, t);
|
||||
return new TransformImpl.ChainedMethodTransform(this, requireNonNull(t));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2022, 2023, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2022, 2024, 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
|
||||
|
@ -36,6 +36,8 @@ import java.lang.classfile.MethodTransform;
|
|||
import jdk.internal.classfile.impl.ClassRemapperImpl;
|
||||
import jdk.internal.javac.PreviewFeature;
|
||||
|
||||
import static java.util.Objects.requireNonNull;
|
||||
|
||||
/**
|
||||
* {@code ClassRemapper} is a {@link ClassTransform}, {@link FieldTransform},
|
||||
* {@link MethodTransform} and {@link CodeTransform}
|
||||
|
@ -64,6 +66,7 @@ public sealed interface ClassRemapper extends ClassTransform permits ClassRemapp
|
|||
* @return new instance of {@code ClassRemapper}
|
||||
*/
|
||||
static ClassRemapper of(Map<ClassDesc, ClassDesc> classMap) {
|
||||
requireNonNull(classMap);
|
||||
return of(desc -> classMap.getOrDefault(desc, desc));
|
||||
}
|
||||
|
||||
|
@ -75,7 +78,7 @@ public sealed interface ClassRemapper extends ClassTransform permits ClassRemapp
|
|||
* @return new instance of {@code ClassRemapper}
|
||||
*/
|
||||
static ClassRemapper of(Function<ClassDesc, ClassDesc> mapFunction) {
|
||||
return new ClassRemapperImpl(mapFunction);
|
||||
return new ClassRemapperImpl(requireNonNull(mapFunction));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -33,6 +33,8 @@ import java.lang.classfile.Label;
|
|||
import jdk.internal.classfile.impl.CodeRelabelerImpl;
|
||||
import jdk.internal.javac.PreviewFeature;
|
||||
|
||||
import static java.util.Objects.requireNonNull;
|
||||
|
||||
/**
|
||||
* A code relabeler is a {@link CodeTransform} replacing all occurrences
|
||||
* of {@link java.lang.classfile.Label} in the transformed code with new instances.
|
||||
|
@ -62,6 +64,7 @@ public sealed interface CodeRelabeler extends CodeTransform permits CodeRelabele
|
|||
* @return a new instance of CodeRelabeler
|
||||
*/
|
||||
static CodeRelabeler of(Map<Label, Label> map) {
|
||||
requireNonNull(map);
|
||||
return of((l, cob) -> map.computeIfAbsent(l, ll -> cob.newLabel()));
|
||||
}
|
||||
|
||||
|
@ -72,6 +75,6 @@ public sealed interface CodeRelabeler extends CodeTransform permits CodeRelabele
|
|||
* @return a new instance of CodeRelabeler
|
||||
*/
|
||||
static CodeRelabeler of(BiFunction<Label, CodeBuilder, Label> mapFunction) {
|
||||
return new CodeRelabelerImpl(mapFunction);
|
||||
return new CodeRelabelerImpl(requireNonNull(mapFunction));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2023, 2024, 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
|
||||
|
|
|
@ -54,6 +54,7 @@ import java.lang.classfile.CodeBuilder;
|
|||
import java.lang.classfile.TypeKind;
|
||||
|
||||
import jdk.internal.constant.ConstantUtils;
|
||||
import jdk.internal.loader.ClassLoaders;
|
||||
import jdk.internal.module.Modules;
|
||||
import jdk.internal.reflect.CallerSensitive;
|
||||
import jdk.internal.reflect.Reflection;
|
||||
|
@ -371,7 +372,8 @@ public class MethodHandleProxies {
|
|||
*/
|
||||
private static byte[] createTemplate(ClassLoader loader, ClassDesc proxyDesc, ClassDesc ifaceDesc,
|
||||
String methodName, List<MethodInfo> methods) {
|
||||
return ClassFile.of(ClassHierarchyResolverOption.of(ClassHierarchyResolver.ofClassLoading(loader)))
|
||||
return ClassFile.of(ClassHierarchyResolverOption.of(ClassHierarchyResolver.ofClassLoading(loader == null ?
|
||||
ClassLoaders.platformClassLoader() : loader)))
|
||||
.build(proxyDesc, clb -> {
|
||||
clb.withSuperclass(CD_Object)
|
||||
.withFlags(ACC_FINAL | ACC_SYNTHETIC)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue