Skip to content

Commit d5e68fd

Browse files
committed
Fixes related to #61. Invalid classes are now skipped. Unrelated, file loading is multi-threaded now. Long class names in the file tree can be truncated, default length is 75
1 parent 20d748a commit d5e68fd

File tree

7 files changed

+90
-15
lines changed

7 files changed

+90
-15
lines changed

src/me/coley/recaf/Input.java

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
import java.util.zip.ZipFile;
2727

2828
import org.objectweb.asm.ClassReader;
29+
import org.objectweb.asm.ClassWriter;
2930
import org.objectweb.asm.commons.ClassRemapper;
3031
import org.objectweb.asm.commons.Remapper;
3132
import org.objectweb.asm.tree.ClassNode;
@@ -372,7 +373,18 @@ private Map<String, byte[]> readClass() throws IOException {
372373
private void addClass(Map<String, byte[]> contents, String name, InputStream is) throws IOException {
373374
byte[] value = Streams.from(is);
374375
try {
375-
String className = new ClassReader(value).getClassName();
376+
ClassReader cr = new ClassReader(value);
377+
String className = cr.getClassName();
378+
// run some basic verification
379+
if (className.endsWith("/")) {
380+
Logging.warn(String.format("Invalid file-name, '%s', skipping this entry", name));
381+
return;
382+
}
383+
if (!verify(cr)) {
384+
Logging.warn(String.format("Invalid code, '%s', skipping this entry", name));
385+
return;
386+
}
387+
376388
classes.add(className);
377389
contents.put(className, value);
378390
} catch (Exception e) {
@@ -470,6 +482,7 @@ public void undo(String name) throws IOException {
470482
* @throws IOException
471483
*/
472484
private FileSystem createSystem(Map<String, byte[]> contents) throws IOException {
485+
Logging.fine("Creating internal file-system for archive...");
473486
FileSystem fs = Jimfs.newFileSystem(Configuration.unix());
474487
for (Entry<String, byte[]> entry : contents.entrySet()) {
475488
Path path = fs.getPath("/" + entry.getKey());
@@ -488,6 +501,7 @@ private FileSystem createSystem(Map<String, byte[]> contents) throws IOException
488501
* @throws IOException
489502
*/
490503
private FileSystem createSystem(Instrumentation instrumentation) throws IOException {
504+
Logging.fine("Creating internal file-system for instrumented runtime...");
491505
FileSystem fs = Jimfs.newFileSystem(Configuration.unix());
492506
// Wrapped return of "readContents" in another map to prevent
493507
// ConcurrentModificationException for when a new class is loaded
@@ -607,6 +621,30 @@ private void instLoaded(String className, byte[] classfileBuffer) throws IOExcep
607621
Bus.post(new ClassLoadInstrumentedEvent(className));
608622
}
609623

624+
/**
625+
* Verify that constant-pool values are not malformed.
626+
*
627+
* @param cr
628+
* ClassReader.
629+
* @return Validity of code, {@code true} for valid.
630+
*/
631+
private static boolean verify(ClassReader cr) {
632+
try {
633+
// The class reader will attempt to parse the raw bytecode stored in
634+
// the array "b" in ClassReader and save it back to a class file via
635+
// ClassWriter. If any errors occur in this process, the code is
636+
// invalid.
637+
//
638+
// This kinda sucks for speed/performance, but hey it means not
639+
// dealing with invalid code (which IMO are not within the scope of
640+
// this tool)
641+
cr.accept(new ClassWriter(0), 0);
642+
} catch (Exception e) {
643+
return false;
644+
}
645+
return true;
646+
}
647+
610648
/**
611649
* Wrapper for system.getPath().
612650
*

src/me/coley/recaf/Recaf.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,13 +32,13 @@ private void onInit(UiInitEvent event) {
3232
LaunchParams params = new LaunchParams();
3333
CommandLine.call(params, System.out, args);
3434
if (params.agent) {
35-
Bus.post(new NewInputEvent(Agent.inst));
35+
NewInputEvent.call(Agent.inst);
3636
return;
3737
}
3838
// load file & class if specified
3939
File file = params.initialFile;
4040
if (file != null && file.exists()) {
41-
Bus.post(new NewInputEvent(file));
41+
NewInputEvent.call(file);
4242
//
4343
Input in = Input.get();
4444
String clazz = params.initialClass;

src/me/coley/recaf/config/impl/ConfDisplay.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,11 @@ public class ConfDisplay extends Config {
4646
*/
4747
@Conf(category = "display", key = "buttonbar")
4848
public boolean toolbar = true;
49+
/**
50+
* Max length of class-name shown in class tree. Helpful for obfuscated programs with long names.
51+
*/
52+
@Conf(category = "display", key = "maxlength.tree")
53+
public int maxLengthTree = 75;
4954

5055

5156
public ConfDisplay() {

src/me/coley/recaf/event/NewInputEvent.java

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,11 @@
44
import java.io.IOException;
55
import java.lang.instrument.Instrumentation;
66

7+
import me.coley.event.Bus;
78
import me.coley.event.Event;
89
import me.coley.recaf.Input;
910
import me.coley.recaf.Logging;
11+
import me.coley.recaf.util.Threads;
1012

1113
/**
1214
* Event for when a new input is loaded.
@@ -36,4 +38,36 @@ public NewInputEvent(Instrumentation instrumentation) throws IOException {
3638
public Input get() {
3739
return input;
3840
}
41+
42+
/**
43+
* Multi-threaded invoke for event.
44+
*
45+
* @param file
46+
* File to load.
47+
*/
48+
public static void call(File file) {
49+
Threads.runLaterFx(0, () -> {
50+
try {
51+
Bus.post(new NewInputEvent(file));
52+
} catch (Exception e) {
53+
Logging.error(e);
54+
}
55+
});
56+
}
57+
58+
/**
59+
* Multi-threaded invoke for event.
60+
*
61+
* @param inst
62+
* Instrumented runtime.
63+
*/
64+
public static void call(Instrumentation inst) {
65+
Threads.runLaterFx(0, () -> {
66+
try {
67+
Bus.post(new NewInputEvent(inst));
68+
} catch (Exception e) {
69+
Logging.error(e);
70+
}
71+
});
72+
}
3973
}

src/me/coley/recaf/ui/FileChoosers.java

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,7 @@ public class FileChoosers {
1616
public static void open() {
1717
File file = open.showOpenDialog(null);
1818
if (file != null) {
19-
try {
20-
Bus.post(new NewInputEvent(file));
21-
} catch (Exception e) {
22-
Logging.error(e);
23-
}
19+
NewInputEvent.call(file);
2420
}
2521
}
2622

src/me/coley/recaf/ui/FxWindow.java

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
package me.coley.recaf.ui;
22

3-
import java.io.IOException;
43
import java.lang.reflect.Field;
54
import java.util.*;
65
import java.util.function.Supplier;
@@ -732,11 +731,7 @@ public void handle(DragEvent e) {
732731
tree.setOnDragDropped(e -> {
733732
Dragboard db = e.getDragboard();
734733
if (db.hasFiles()) {
735-
try {
736-
Bus.post(new NewInputEvent(db.getFiles().get(0)));
737-
} catch (IOException ex) {
738-
Logging.error(ex);
739-
}
734+
NewInputEvent.call(db.getFiles().get(0));
740735
}
741736
});
742737
// Custom tree renderering.
@@ -754,7 +749,12 @@ public void updateItem(String item, boolean empty) {
754749
boolean cont = input.getClasses().containsKey(item);
755750
Node fxImage = cont ? Icons.getClass(input.getClass(item).access) : new ImageView(Icons.CL_PACKAGE);
756751
setGraphic(fxImage);
757-
setText(cont ? trim(item) : item);
752+
String name = cont ? trim(item) : item;
753+
int max = ConfDisplay.instance().maxLengthTree;
754+
if (name.length() > max) {
755+
name = name.substring(0, max);
756+
}
757+
setText(name);
758758
}
759759
}
760760
});

src/resources/lang/en.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,8 @@
4949
"display.loglevel.desc": "Level of logging to display in console.",
5050
"display.buttonbar.name": "Show button bar",
5151
"display.buttonbar.desc": "Show the easy-access button-bar in the UI. Restart to apply changes.",
52+
"display.maxlength.tree.name": "Max tree name length",
53+
"display.maxlength.tree.desc": "The max length of names in the file tree. Useful for obfuscated assemblies with crazy names.",
5254

5355
"keybinds": "Keybinds",
5456
"keybinds.active.name": "Use keybinds",

0 commit comments

Comments
 (0)