| benf.org : other : cfr : Renaming fields - (For obfuscation or otherwise). |
I finally got around to handling this in CFR 0.92 - use '--renamedupmembers true'
nb: This is related to, but different from illegal field/method names and duplicate method renaming
Some decompiled code occasionally ends up with the same field name repeated multiple times - i.e.
/*
* Duplicate member names - consider using --renamedupmembers true
*/
public class NameTest22 {
public float fred;
public int fred;
public long fred;
public NameTest22(int n) {
this.fred = n + 1;
this.fred = n + 3;
this.fred = n + 4;
}
public String toString() {
return "NameTest22{fred=" + this.fred + ", free=" + this.fred + ", fref=" + this.fred + '}';
}
public static void main(String[] arrstring) {
System.out.println(new NameTest22(3));
}
}
(To reproduce this from legit java, you could (a) simply (as I have) use a hex editor to rename fields 'free' and 'fref' to 'fred', or (b) change the constpool entries so that they all point to the one 'fred' string.)
| Using the excellent Hex-fiend editor | ||
![]() | → | ![]() |
There are many fine class file editors out there, but that's sort of out of scope!
The issue here is that these fields now apparently have exactly the same name - that's illegal java!
The JVM spec section 5.4.3.2 says the following: If C declares a field with the name and descriptor specified by the field reference, field lookup succeeds.
Note - BOTH name and descriptor (type information) are used for the JVM to uniquely identify a field. This means that according to the JVM, it's perfectly legitimate to have two fields of a different type with the same name. It's just an example where the constraints of the java language are slightly tighter than the constraints of the JVM.
Nope. Sad JVM - which is of course entirely consistent with the specification above.
Exception in thread "main" java.lang.ClassFormatError: Duplicate field name&signature in class file org/benf/cfr/tests/NameTest22 at java.lang.ClassLoader.defineClass1(Native Method) at java.lang.ClassLoader.defineClass(ClassLoader.java:760)
Maybe a bit much - I think this is about as effective an obfuscation as turning a sign saying 'Top secret base this way' upside down.
This one seems much more likely to me! In my example above, I hacked existing symbols so they had the same text. However, it would be equivalent to remove the duplicate symbols from the Const Pool altogether - which (obviously!) saves some space. Not much, but perhaps in the world of Mobile Java, this is still a thing worth having.
CFR will now decorate any class file it thinks suffers from this issue with this comment
/* * Duplicate member names - consider using --renamedupmembers true */
So.... just do that! Because the types of the fields are part of the key, this flag appends _type to any duplicate field.
/*
* Decompiled with CFR
*/
package org.benf.cfr.tests;
import java.io.PrintStream;
public class NameTest22 {
public float fred_float;
public int fred_int;
public long fred_long;
public NameTest22(int n) {
this.fred_int = n + 1;
this.fred_float = n + 3;
this.fred_long = n + 4;
}
public String toString() {
return "NameTest22{fred=" + this.fred_float + ", free=" + this.fred_int + ", fref=" + this.fred_long + '}';
}
public static void main(String[] arrstring) {
System.out.println(new NameTest22(3));
}
}
Please note: CFR will not automatically enable this flag.
Two reasons:
| Last updated 01/2015 |