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:
Chen Liang 2024-10-14 17:21:10 +00:00
parent 60713463c7
commit a2c775222e
36 changed files with 249 additions and 116 deletions

View file

@ -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());
}
}

View file

@ -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) {

View file

@ -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) {

View file

@ -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));
}
}

View file

@ -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));
}
}

View file

@ -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));
}
}

View file

@ -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));
}
}

View file

@ -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));
}
/**

View file

@ -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));
}
}

View file

@ -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

View file

@ -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)