From 9f0dbda0363ecaeaa5fde2aa49e33f542b9b85e4 Mon Sep 17 00:00:00 2001 From: Jasmine Karthikeyan <25208576+jaskarth@users.noreply.github.com> Date: Sun, 18 Aug 2024 15:56:02 -0400 Subject: [PATCH] Avoid race condition crashes when handling duplicate classes --- .../java/decompiler/main/ClassesProcessor.java | 16 +++++++++++++++- .../decompiler/main/extern/IContextSource.java | 5 ++++- .../java/decompiler/struct/ContextUnit.java | 12 +++++++----- 3 files changed, 26 insertions(+), 7 deletions(-) diff --git a/src/org/jetbrains/java/decompiler/main/ClassesProcessor.java b/src/org/jetbrains/java/decompiler/main/ClassesProcessor.java index 567a3feca5..3252b57772 100644 --- a/src/org/jetbrains/java/decompiler/main/ClassesProcessor.java +++ b/src/org/jetbrains/java/decompiler/main/ClassesProcessor.java @@ -102,8 +102,22 @@ public void loadClasses(IIdentifierRenamer renamer) { excludedMatcher = Pattern.compile(excludedRegex).matcher(""); } + // Filter any duplicate classes + + List ownClasses = context.getOwnClasses(); + List classes = new ArrayList<>(); + Set names = new LinkedHashSet<>(); + + for (StructClass cl : ownClasses) { + if (names.add(cl.qualifiedName)) { + classes.add(cl); + } else { + DecompilerContext.getLogger().writeMessage("Skipping processing already existing class: " + cl.qualifiedName, IFernflowerLogger.Severity.ERROR); + } + } + // create class nodes - for (StructClass cl : context.getOwnClasses()) { + for (StructClass cl : classes) { if (excludedMatcher != null && excludedMatcher.reset(cl.qualifiedName).matches()) { continue; } diff --git a/src/org/jetbrains/java/decompiler/main/extern/IContextSource.java b/src/org/jetbrains/java/decompiler/main/extern/IContextSource.java index 3dd82b1b8a..51e52eba9c 100644 --- a/src/org/jetbrains/java/decompiler/main/extern/IContextSource.java +++ b/src/org/jetbrains/java/decompiler/main/extern/IContextSource.java @@ -260,6 +260,9 @@ public String path() { } } - + @Override + public String toString() { + return "E[" + basePath + "]"; + } } } diff --git a/src/org/jetbrains/java/decompiler/struct/ContextUnit.java b/src/org/jetbrains/java/decompiler/struct/ContextUnit.java index b1fd3b753b..bb39d60163 100644 --- a/src/org/jetbrains/java/decompiler/struct/ContextUnit.java +++ b/src/org/jetbrains/java/decompiler/struct/ContextUnit.java @@ -13,10 +13,7 @@ import java.io.IOException; import java.io.InputStream; import java.nio.charset.StandardCharsets; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.LinkedList; -import java.util.List; +import java.util.*; import java.util.concurrent.*; import java.util.concurrent.atomic.AtomicInteger; import java.util.function.Function; @@ -150,13 +147,18 @@ public void save(final Function loader) throws IOException ForkJoinPool pool = new ForkJoinPool(threads, namingScheme(), null, true); final DecompilerContext rootContext = DecompilerContext.getCurrentContext(); final List toDump = new ArrayList<>(classEntries.size()); + Set seen = new LinkedHashSet<>(); // collect classes for (int i = 0; i < classEntries.size(); i++) { StructClass cl = loader.apply(classEntries.get(i)); String entryName = decompiledData.getClassEntryName(cl, classEntries.get(i)); if (entryName != null) { - toDump.add(new ClassContext(cl, entryName)); + if (seen.add(cl.qualifiedName)) { + toDump.add(new ClassContext(cl, entryName)); + } else { + DecompilerContext.getLogger().writeMessage("Skipping writing already existing class: " + cl.qualifiedName, IFernflowerLogger.Severity.ERROR); + } } }