From c65774e2cee6454bf55a7d16eb9c2be0da97ec71 Mon Sep 17 00:00:00 2001 From: Matt Date: Tue, 7 Jan 2025 01:27:39 -0500 Subject: [PATCH] Fix regression in 529061bc7 breaking ClassInfo equality checks Because the info-importer is can be configured to skip method metadata (which it will by default) this broke the tests where the other model was using the metadata. Realistically if two JVM classes have the same byte-array then they are equal, and we dont need to do any model checking. Only if the array is different should we fall back to model checks. --- .../software/coley/recaf/info/BasicJvmClassInfo.java | 4 +++- .../recaf/info/builder/JvmClassInfoBuilder.java | 12 ++++++++++++ .../software/coley/recaf/info/JvmClassInfoTest.java | 6 +++++- 3 files changed, 20 insertions(+), 2 deletions(-) diff --git a/recaf-core/src/main/java/software/coley/recaf/info/BasicJvmClassInfo.java b/recaf-core/src/main/java/software/coley/recaf/info/BasicJvmClassInfo.java index 760c74250..bdbc32023 100644 --- a/recaf-core/src/main/java/software/coley/recaf/info/BasicJvmClassInfo.java +++ b/recaf-core/src/main/java/software/coley/recaf/info/BasicJvmClassInfo.java @@ -49,12 +49,14 @@ public int getVersion() { public boolean equals(Object o) { if (this == o) return true; if (o == null) return false; - if (!super.equals(o)) return false; if (o instanceof JvmClassInfo other) { if (version != other.getVersion()) return false; return Arrays.equals(bytecode, other.getBytecode()); + } else if (!super.equals(o)) { + return false; } + return false; } diff --git a/recaf-core/src/main/java/software/coley/recaf/info/builder/JvmClassInfoBuilder.java b/recaf-core/src/main/java/software/coley/recaf/info/builder/JvmClassInfoBuilder.java index 9811c0cb8..42cc9ac6f 100644 --- a/recaf-core/src/main/java/software/coley/recaf/info/builder/JvmClassInfoBuilder.java +++ b/recaf-core/src/main/java/software/coley/recaf/info/builder/JvmClassInfoBuilder.java @@ -85,6 +85,18 @@ public JvmClassInfoBuilder(@Nonnull ClassReader reader) { adaptFrom(reader); } + /** + * Creates a builder with data pulled from the given bytecode. + * + * @param reader + * ASM class reader to read bytecode from. + * @param readerFlags + * Reader flags to use when populating information via {@link ClassReader#accept(ClassVisitor, int)}. + */ + public JvmClassInfoBuilder(@Nonnull ClassReader reader, int readerFlags) { + adaptFrom(reader, readerFlags); + } + /** * Creates a builder with the given bytecode. * diff --git a/recaf-core/src/test/java/software/coley/recaf/info/JvmClassInfoTest.java b/recaf-core/src/test/java/software/coley/recaf/info/JvmClassInfoTest.java index b2fff45ff..dadde15b1 100644 --- a/recaf-core/src/test/java/software/coley/recaf/info/JvmClassInfoTest.java +++ b/recaf-core/src/test/java/software/coley/recaf/info/JvmClassInfoTest.java @@ -2,12 +2,14 @@ import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; +import org.objectweb.asm.Opcodes; import software.coley.cafedude.classfile.VersionConstants; import software.coley.recaf.test.TestClassUtils; import software.coley.recaf.test.dummy.AccessibleFields; import software.coley.recaf.util.ByteHeaderUtil; import java.io.IOException; +import java.util.Arrays; import static org.junit.jupiter.api.Assertions.*; @@ -93,8 +95,10 @@ void toBuilder() { "Direct copy via builder should have same class equality"); // With modification + byte[] modifiedBytecode = Arrays.copyOf(accessibleFields.getBytecode(), accessibleFields.getBytecode().length); + modifiedBytecode[5] = 1; // Change minor version to any non-zero value JvmClassInfo builderModifiedCopy = accessibleFields.toJvmClassBuilder() - .withName("Modified") + .withBytecode(modifiedBytecode) .build(); assertNotEquals(accessibleFields, builderModifiedCopy, "Direct copy via builder should have same class equality");