Skip to content

Commit

Permalink
Handle class parsing errors more gracefully
Browse files Browse the repository at this point in the history
Currently there can be some classes in the wild that can not be parsed
by ASM, instead of completely fail, we just print the cause to the log
and go on.

(cherry picked from commit fdc0adf)
  • Loading branch information
laeubi committed Jan 20, 2025
1 parent da61b87 commit 020ac75
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,8 @@ public void execute() throws MojoExecutionException, MojoFailureException {
Map<String, Version> lowestPackageVersion = new HashMap<>();
Map<String, Set<Version>> allPackageVersion = new HashMap<>();
Set<String> packageWithError = new HashSet<>();
Function<String, Optional<ClassMethods>> classResolver = DependencyAnalyzer
DependencyAnalyzer dependencyAnalyzer = new DependencyAnalyzer((m, e) -> getLog().error(m, e));
Function<String, Optional<ClassMethods>> classResolver = dependencyAnalyzer
.createDependencyClassResolver(jrtClassResolver, artifacts);
for (GenericInfo genericInfo : requirements) {
if (PackageNamespace.PACKAGE_NAMESPACE.equals(genericInfo.getNamespace())) {
Expand Down Expand Up @@ -223,7 +224,7 @@ public void execute() throws MojoExecutionException, MojoFailureException {
}
ClassCollection collection = analyzeCache.get(artifact);
if (collection == null) {
collection = DependencyAnalyzer.analyzeProvides(artifact.toFile(), classResolver, null);
collection = dependencyAnalyzer.analyzeProvides(artifact.toFile(), classResolver);
analyzeCache.put(artifact, collection);
}
boolean ok = true;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import java.util.Enumeration;
import java.util.List;
import java.util.Optional;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.jar.JarEntry;
Expand All @@ -34,6 +35,11 @@ public class DependencyAnalyzer {

static final String CLASS_SUFFIX = ".class";
static final int ASM_API = Opcodes.ASM9;
private BiConsumer<String, Throwable> errorConsumer;

public DependencyAnalyzer(BiConsumer<String, Throwable> errorConsumer) {
this.errorConsumer = errorConsumer;
}

public static String getPackageName(String className) {
className = className.replace('/', '.');
Expand All @@ -44,7 +50,7 @@ public static String getPackageName(String className) {
return className;
}

public static Function<String, Optional<ClassMethods>> createDependencyClassResolver(JrtClasses jrtClassResolver,
public Function<String, Optional<ClassMethods>> createDependencyClassResolver(JrtClasses jrtClassResolver,
DependencyArtifacts artifacts) throws MojoFailureException {
ClassCollection allClassMethods = new ClassCollection();
Function<String, Optional<ClassMethods>> function = allClassMethods.chain(jrtClassResolver);
Expand Down Expand Up @@ -76,7 +82,12 @@ public static List<ClassUsage> analyzeUsage(File file, JrtClasses jre) throws Mo
}
}

public static ClassCollection analyzeProvides(File file, Function<String, Optional<ClassMethods>> classResolver,
public ClassCollection analyzeProvides(File file, Function<String, Optional<ClassMethods>> classResolver)
throws MojoFailureException {
return analyzeProvides(file, classResolver, null);
}

public ClassCollection analyzeProvides(File file, Function<String, Optional<ClassMethods>> classResolver,
Consumer<ClassMethods> consumer) throws MojoFailureException {
try {
ClassCollection local = new ClassCollection();
Expand All @@ -88,7 +99,16 @@ public static ClassCollection analyzeProvides(File file, Function<String, Option
String name = jarEntry.getName();
if (name.endsWith(CLASS_SUFFIX)) {
InputStream stream = jar.getInputStream(jarEntry);
ClassMethods methods = new ClassMethods(stream.readAllBytes(), resolver);
ClassMethods methods;
try {
methods = new ClassMethods(stream.readAllBytes(), resolver);
} catch (RuntimeException e) {
// can't analyze this class, example of errors is
// java.lang.ArrayIndexOutOfBoundsException: Index 29 out of bounds for length 9
errorConsumer.accept("Can't analyze class '" + name + "' because of error while parsing",
e);
continue;
}
if (consumer != null) {
consumer.accept(methods);
}
Expand Down

0 comments on commit 020ac75

Please sign in to comment.