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

Add better reporting if ASM fails to parse a class with an unspecified RuntimeException #174

Merged
merged 1 commit into from
Sep 2, 2020
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
9 changes: 9 additions & 0 deletions src/main/java/de/thetaphi/forbiddenapis/AsmUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.Locale;
import java.util.Objects;
import java.util.regex.Pattern;

import org.objectweb.asm.ClassReader;
Expand Down Expand Up @@ -181,5 +182,13 @@ public static ClassReader readAndPatchClass(InputStream in) throws IOException {
if (false) patchClassMajorVersion(bytecode, Opcodes.V15 + 1, Opcodes.V15);
return new ClassReader(bytecode);
}

/** Returns true, if the given {@link RuntimeException} was caused by ASM's ClassReader */
public static boolean isExceptionInAsmClassReader(RuntimeException re) {
// Because of javac bugs some class files are broken and cause RuntimeExceptions like AIOOBE
// We analyze stack trace if this is caused by ASM's ClassReader and not our code:
final StackTraceElement[] stack = re.getStackTrace();
return stack.length > 0 && Objects.equals(ClassReader.class.getName(), stack[0].getClassName());
}

}
22 changes: 21 additions & 1 deletion src/main/java/de/thetaphi/forbiddenapis/Checker.java
Original file line number Diff line number Diff line change
Expand Up @@ -309,6 +309,11 @@ public ClassSignature lookupRelatedClass(String internalName, String internalNam
}
} catch (IOException ioe) {
throw new RelatedClassLoadingException(ioe, Type.getObjectType(internalNameOrig).getClassName());
} catch (RuntimeException re) {
if (AsmUtils.isExceptionInAsmClassReader(re)) {
throw new RelatedClassLoadingException(re, Type.getObjectType(internalNameOrig).getClassName());
}
throw re;
uschindler marked this conversation as resolved.
Show resolved Hide resolved
}
}

Expand Down Expand Up @@ -419,8 +424,23 @@ private int checkClass(final ClassReader reader, Pattern suppressAnnotationsPatt
}
msg.append(": ").append(cause);
msg.append(" (while looking up details about referenced class '").append(rcle.getClassName()).append("')");
assert cause != null && (cause instanceof IOException || cause instanceof ClassNotFoundException);
assert cause != null && (cause instanceof IOException || cause instanceof ClassNotFoundException || cause instanceof RuntimeException);
throw new ForbiddenApiException(msg.toString(), cause);
} catch (RuntimeException re) {
if (AsmUtils.isExceptionInAsmClassReader(re)) {
final StringBuilder msg = new StringBuilder()
.append("Failed to parse class '")
.append(className)
.append('\'');
final String source = scanner.getSourceFile();
if (source != null) {
msg.append(" (").append(source).append(')');
}
msg.append(": ").append(re);
throw new ForbiddenApiException(msg.toString(), re);
}
// else rethrow (it's occuring in our code):
uschindler marked this conversation as resolved.
Show resolved Hide resolved
throw re;
}
final List<ForbiddenViolation> violations = scanner.getSortedViolations();
final Pattern splitter = Pattern.compile(Pattern.quote(ForbiddenViolation.SEPARATOR));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,11 @@ public RelatedClassLoadingException(IOException e, String className) {
this.className = className;
}

public RelatedClassLoadingException(RuntimeException e, String className) {
super(e);
this.className = className;
}

public Exception getException() {
return (Exception) getCause();
}
Expand Down