Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix false positives in JDK-17 with RandomSupport #178

Merged
merged 3 commits into from
Apr 23, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 19 additions & 19 deletions src/main/java/de/thetaphi/forbiddenapis/Checker.java
Original file line number Diff line number Diff line change
Expand Up @@ -70,9 +70,9 @@ public static enum Option {
final EnumSet<Option> options;

/** Classes to check: key is the binary name (dotted) */
final Map<String,ClassSignature> classesToCheck = new HashMap<>();
final Map<String,ClassMetadata> classesToCheck = new HashMap<>();
/** Cache of loaded classes: key is the binary name (dotted) */
final Map<String,ClassSignature> classpathClassCache = new HashMap<>();
final Map<String,ClassMetadata> classpathClassCache = new HashMap<>();

final Signatures forbiddenSignatures;

Expand Down Expand Up @@ -185,7 +185,7 @@ public Checker(Logger logger, ClassLoader loader, EnumSet<Option> options) {
}

/** Loads the class from Java9's module system and uses reflection to get methods and fields. */
private ClassSignature loadClassFromJigsaw(String classname) throws IOException {
private ClassMetadata loadClassFromJigsaw(String classname) throws IOException {
if (method_Class_getModule == null || method_Module_getName == null) {
return null; // not Jigsaw Module System
}
Expand All @@ -200,7 +200,7 @@ private ClassSignature loadClassFromJigsaw(String classname) throws IOException
return null; // not found
}

return new ClassSignature(clazz, AsmUtils.isRuntimeModule(moduleName));
return new ClassMetadata(clazz, AsmUtils.isRuntimeModule(moduleName));
}

private boolean isRuntimePath(URL url) throws IOException {
Expand Down Expand Up @@ -233,9 +233,9 @@ private boolean isRuntimeClass(URLConnection conn) throws IOException {

/** Reads a class (binary name) from the given {@link ClassLoader}. If not found there, falls back to the list of classes to be checked. */
@Override
public ClassSignature getClassFromClassLoader(final String clazz) throws ClassNotFoundException,IOException {
public ClassMetadata getClassFromClassLoader(final String clazz) throws ClassNotFoundException,IOException {
if (classpathClassCache.containsKey(clazz)) {
final ClassSignature c = classpathClassCache.get(clazz);
final ClassMetadata c = classpathClassCache.get(clazz);
if (c == null) {
throw new ClassNotFoundException(clazz);
}
Expand All @@ -255,7 +255,7 @@ public ClassSignature getClassFromClassLoader(final String clazz) throws ClassNo
// if class is too new for this JVM, we try to load it as Class<?> via Jigsaw
// (only if it's a runtime class):
if (isRuntimeClass) {
final ClassSignature c = loadClassFromJigsaw(clazz);
final ClassMetadata c = loadClassFromJigsaw(clazz);
if (c != null) {
classpathClassCache.put(clazz, c);
return c;
Expand All @@ -265,18 +265,18 @@ public ClassSignature getClassFromClassLoader(final String clazz) throws ClassNo
"The class file format of '%s' (loaded from location '%s') is too recent to be parsed by ASM.",
clazz, url.toExternalForm()));
}
final ClassSignature c = new ClassSignature(cr, isRuntimeClass, false);
final ClassMetadata c = new ClassMetadata(cr, isRuntimeClass, false);
classpathClassCache.put(clazz, c);
return c;
} else {
final ClassSignature c = loadClassFromJigsaw(clazz);
final ClassMetadata c = loadClassFromJigsaw(clazz);
if (c != null) {
classpathClassCache.put(clazz, c);
return c;
}
}
// try to get class from our list of classes we are checking:
final ClassSignature c = classesToCheck.get(clazz);
final ClassMetadata c = classesToCheck.get(clazz);
if (c != null) {
classpathClassCache.put(clazz, c);
return c;
Expand All @@ -288,7 +288,7 @@ public ClassSignature getClassFromClassLoader(final String clazz) throws ClassNo
}

@Override
public ClassSignature lookupRelatedClass(String internalName, String internalNameOrig) {
public ClassMetadata lookupRelatedClass(String internalName, String internalNameOrig) {
final Type type = Type.getObjectType(internalName);
if (type.getSort() != Type.OBJECT) {
return null;
Expand Down Expand Up @@ -361,8 +361,8 @@ public void addClassToCheck(final InputStream in, String name) throws IOExceptio
throw new IllegalArgumentException(String.format(Locale.ENGLISH,
"The class file format of '%s' is too recent to be parsed by ASM.", name));
}
final String binaryName = Type.getObjectType(reader.getClassName()).getClassName();
classesToCheck.put(binaryName, new ClassSignature(reader, false, true));
final ClassMetadata metadata = new ClassMetadata(reader, false, true);
classesToCheck.put(metadata.getBinaryClassName(), metadata);
}

/** Parses and adds a class from the given file to the list of classes to check. Does not log anything. */
Expand Down Expand Up @@ -407,11 +407,11 @@ public void addSuppressAnnotation(String annoName) {
}

/** Parses a class and checks for valid method invocations */
private int checkClass(final ClassReader reader, Pattern suppressAnnotationsPattern) throws ForbiddenApiException {
final String className = Type.getObjectType(reader.getClassName()).getClassName();
final ClassScanner scanner = new ClassScanner(this, forbiddenSignatures, suppressAnnotationsPattern);
private int checkClass(ClassMetadata c, Pattern suppressAnnotationsPattern) throws ForbiddenApiException {
final String className = c.getBinaryClassName();
final ClassScanner scanner = new ClassScanner(c, this, forbiddenSignatures, suppressAnnotationsPattern);
try {
reader.accept(scanner, ClassReader.SKIP_FRAMES);
c.getReader().accept(scanner, ClassReader.SKIP_FRAMES);
} catch (RelatedClassLoadingException rcle) {
final Exception cause = rcle.getException();
final StringBuilder msg = new StringBuilder()
Expand Down Expand Up @@ -456,8 +456,8 @@ public void run() throws ForbiddenApiException {
logger.info("Scanning classes for violations...");
int errors = 0;
final Pattern suppressAnnotationsPattern = AsmUtils.glob2Pattern(suppressAnnotations.toArray(new String[suppressAnnotations.size()]));
for (final ClassSignature c : classesToCheck.values()) {
errors += checkClass(c.getReader(), suppressAnnotationsPattern);
for (final ClassMetadata c : classesToCheck.values()) {
errors += checkClass(c, suppressAnnotationsPattern);
}

final String message = String.format(Locale.ENGLISH,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,22 +33,23 @@

/** Utility class that is used to get an overview of all fields and implemented
* methods of a class. It make the signatures available as Sets. */
final class ClassSignature implements Constants {
final class ClassMetadata implements Constants {
private ClassReader reader;

public final boolean isRuntimeClass, isNonPortableRuntime;
public final boolean isRuntimeClass, isNonPortableRuntime, isInterface;
public final Set<Method> methods;
public final Set<String> fields, signaturePolymorphicMethods;
public final String className, superName;
public final String[] interfaces;

/** Builds the information from an ASM ClassReader */
public ClassSignature(final ClassReader classReader, boolean isRuntimeClass, boolean withReader) {
public ClassMetadata(final ClassReader classReader, boolean isRuntimeClass, boolean withReader) {
this.reader = withReader ? classReader : null;
this.isRuntimeClass = isRuntimeClass;
this.className = classReader.getClassName();
this.superName = classReader.getSuperName();
this.interfaces = classReader.getInterfaces();
this.isInterface = (classReader.getAccess() & Opcodes.ACC_INTERFACE) != 0;
final Set<Method> methods = new HashSet<>();
final Set<String> fields = new HashSet<>();
final Set<String> signaturePolymorphicMethods = new HashSet<>();
Expand Down Expand Up @@ -80,7 +81,7 @@ public FieldVisitor visitField(int access, String name, String desc, String sign
}

/** Alternative ctor that can be used to build the information via reflection from an already loaded class. Useful for Java 9 Jigsaw. */
public ClassSignature(final Class<?> clazz, boolean isRuntimeClass) {
public ClassMetadata(final Class<?> clazz, boolean isRuntimeClass) {
this.reader = null; // no reader available!
this.isRuntimeClass = isRuntimeClass;
this.className = Type.getType(clazz).getInternalName();
Expand All @@ -91,6 +92,7 @@ public ClassSignature(final Class<?> clazz, boolean isRuntimeClass) {
for (int i = 0; i < interfClasses.length; i++) {
this.interfaces[i] = Type.getType(interfClasses[i]).getInternalName();
}
this.isInterface = clazz.isInterface();
final Set<Method> methods = new HashSet<>();
final Set<String> fields = new HashSet<>();
final Set<String> signaturePolymorphicMethods = new HashSet<>();
Expand Down
Loading