mirror of
https://github.com/pxb1988/dex2jar.git
synced 2024-11-26 22:50:42 +00:00
fix type detect on arrays
fix https://github.com/pxb1988/dex2jar/issues/28
This commit is contained in:
parent
d9baaa5779
commit
0d48e49275
@ -16,8 +16,6 @@
|
||||
*/
|
||||
package com.googlecode.dex2jar.ir.ts;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import com.googlecode.dex2jar.ir.IrMethod;
|
||||
import com.googlecode.dex2jar.ir.TypeClass;
|
||||
import com.googlecode.dex2jar.ir.expr.*;
|
||||
@ -29,6 +27,8 @@ import com.googlecode.dex2jar.ir.stmt.Stmt.E1Stmt;
|
||||
import com.googlecode.dex2jar.ir.stmt.Stmt.E2Stmt;
|
||||
import com.googlecode.dex2jar.ir.stmt.Stmt.ST;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Type and correct Exprs
|
||||
*
|
||||
@ -100,7 +100,7 @@ public class TypeTransformer implements Transformer {
|
||||
|
||||
public final Value value;
|
||||
/**
|
||||
* same use, have same {@link #clz}
|
||||
* same use, have same
|
||||
*/
|
||||
public Set<TypeRef> sameValues = null;
|
||||
/**
|
||||
@ -111,82 +111,120 @@ public class TypeTransformer implements Transformer {
|
||||
/**
|
||||
* reference to root
|
||||
*/
|
||||
public TypeRef arrayRoot = null;
|
||||
public Set<TypeRef> arrayRoots = null;
|
||||
|
||||
public TypeRef mergedArrayRoot;
|
||||
public TypeRef mergedArrayValue;
|
||||
|
||||
public Set<TypeRef> parents = null;
|
||||
public Set<TypeRef> children = null;
|
||||
|
||||
public void setArrayValueShareT(SharedT arrayValueShareT) {
|
||||
this.arrayValueShareT = arrayValueShareT;
|
||||
public TypeClass clz = TypeClass.UNKNOWN;
|
||||
public String provideDesc = null;
|
||||
public Set<String> uses;
|
||||
|
||||
private TypeRef next;
|
||||
|
||||
public void linkArray() {
|
||||
if (arrayRoots != null) {
|
||||
for (TypeRef root : arrayRoots) {
|
||||
if (mergedArrayRoot == null) {
|
||||
mergedArrayRoot = root;
|
||||
} else {
|
||||
mergedArrayRoot.merge(root);
|
||||
}
|
||||
if (root.mergedArrayValue == null) {
|
||||
root.mergedArrayValue = this;
|
||||
} else {
|
||||
root.mergedArrayValue.merge(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (gArrayValues != null) {
|
||||
for (TypeRef leafe : gArrayValues) {
|
||||
if (mergedArrayValue == null) {
|
||||
mergedArrayValue = leafe;
|
||||
} else {
|
||||
mergedArrayValue.merge(leafe);
|
||||
}
|
||||
|
||||
public TypeClass getClz() {
|
||||
return t.getReal().clz;
|
||||
if (leafe.mergedArrayRoot == null) {
|
||||
leafe.mergedArrayRoot = this;
|
||||
} else {
|
||||
leafe.mergedArrayRoot.merge(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (sArrayValues != null) {
|
||||
for (TypeRef leafe : sArrayValues) {
|
||||
if (mergedArrayValue == null) {
|
||||
mergedArrayValue = leafe;
|
||||
} else {
|
||||
mergedArrayValue.merge(leafe);
|
||||
}
|
||||
if (leafe.mergedArrayRoot == null) {
|
||||
leafe.mergedArrayRoot = this;
|
||||
} else {
|
||||
leafe.mergedArrayRoot.merge(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void setClz(TypeClass clz) {
|
||||
this.t.getReal().clz = clz;
|
||||
}
|
||||
|
||||
static class SharedT {
|
||||
private TypeClass clz = TypeClass.UNKNOWN;
|
||||
private String provideDesc = null;
|
||||
private Set<String> uses;
|
||||
SharedT next;
|
||||
|
||||
SharedT getReal() {
|
||||
SharedT _this = this;
|
||||
SharedT _next = this.next;
|
||||
while (_next != null) {
|
||||
_this = _next;
|
||||
_next = _next.next;
|
||||
}
|
||||
return _this;
|
||||
}
|
||||
|
||||
boolean merge(SharedT b) {
|
||||
SharedT a = this;
|
||||
public void merge(TypeRef other) {
|
||||
TypeRef a = getReal();
|
||||
TypeRef b = other.getReal();
|
||||
if (a == b) {
|
||||
return false;
|
||||
return;
|
||||
}
|
||||
if (a.mergedArrayRoot != null && b.mergedArrayRoot != null) {
|
||||
a.mergedArrayRoot.merge(b.mergedArrayRoot);
|
||||
} else if (a.mergedArrayRoot != null) {
|
||||
b.mergedArrayRoot = a.mergedArrayRoot;
|
||||
} else {
|
||||
a.mergedArrayRoot = b.mergedArrayRoot;
|
||||
}
|
||||
if (a.mergedArrayValue != null && b.mergedArrayValue != null) {
|
||||
a.mergedArrayValue.merge(b.mergedArrayValue);
|
||||
} else if (a.mergedArrayValue != null) {
|
||||
b.mergedArrayValue = a.mergedArrayValue;
|
||||
} else {
|
||||
a.mergedArrayValue = b.mergedArrayValue;
|
||||
}
|
||||
|
||||
b.next = a;
|
||||
|
||||
if (a.provideDesc == null) {
|
||||
a.provideDesc = b.provideDesc;
|
||||
} else if (b.provideDesc != null) {
|
||||
a.provideDesc = TypeAnalyze.mergeProviderType(a.provideDesc, b.provideDesc);
|
||||
b.provideDesc = null;
|
||||
}
|
||||
if (b.uses != null) {
|
||||
if (a.uses == null) {
|
||||
a.uses = new HashSet<>();
|
||||
}
|
||||
a.uses.addAll(b.uses);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
b.uses = null;
|
||||
}
|
||||
|
||||
private SharedT arrayValueShareT;
|
||||
|
||||
SharedT getArrayValueShareT() {
|
||||
if (arrayValueShareT == null) {
|
||||
arrayValueShareT = new SharedT();
|
||||
return arrayValueShareT;
|
||||
} else {
|
||||
return arrayValueShareT.getReal();
|
||||
}
|
||||
}
|
||||
|
||||
boolean mergeT(TypeRef other) {
|
||||
SharedT a = t.getReal();
|
||||
SharedT b = other.t.getReal();
|
||||
this.t = a;
|
||||
other.t = a;
|
||||
if (a != b) {
|
||||
updateTypeClass(other.getClz());
|
||||
return a.merge(b);
|
||||
public TypeClass getClz() {
|
||||
return this.getReal().clz;
|
||||
}
|
||||
return false;
|
||||
|
||||
public void setClz(TypeClass clz) {
|
||||
this.getReal().clz = clz;
|
||||
}
|
||||
|
||||
private TypeRef getReal() {
|
||||
TypeRef x = this;
|
||||
while (x.next != null) {
|
||||
x = x.next;
|
||||
}
|
||||
return x;
|
||||
}
|
||||
SharedT t = new SharedT();
|
||||
|
||||
public TypeRef(Value value) {
|
||||
super();
|
||||
@ -195,25 +233,27 @@ public class TypeTransformer implements Transformer {
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
String p = this.getUses() == null ? "[]" : this.getUses().toString();
|
||||
return getClz() + "::" + value + ": " + this.getProvideDesc() + " > {" + p.substring(1, p.length() - 1) + "}";
|
||||
TypeRef real = getReal();
|
||||
String p = real.uses == null ? "[]" : real.uses.toString();
|
||||
return real.clz + "::" + value + ": " + real.provideDesc + " > {" + p.substring(1, p.length() - 1) + "}";
|
||||
}
|
||||
|
||||
public String getType() {
|
||||
if (getClz() == TypeClass.OBJECT) {
|
||||
TypeClass clz = getClz();
|
||||
if (clz == TypeClass.OBJECT) {
|
||||
if (getProvideDesc().length() == 1) {
|
||||
return "Ljava/lang/Object;";
|
||||
} else {
|
||||
return getProvideDesc();
|
||||
}
|
||||
}
|
||||
if (getClz().fixed && getClz() != TypeClass.INT) {
|
||||
if (clz.fixed && clz != TypeClass.INT) {
|
||||
if (getProvideDesc() == null) {
|
||||
throw new RuntimeException();
|
||||
}
|
||||
return getProvideDesc();
|
||||
}
|
||||
if (getClz() == TypeClass.JD) { // prefere Long if wide
|
||||
if (clz == TypeClass.JD) { // prefere Long if wide
|
||||
return "J";
|
||||
}
|
||||
if (getUses() != null) {
|
||||
@ -224,7 +264,7 @@ public class TypeTransformer implements Transformer {
|
||||
}
|
||||
}
|
||||
|
||||
switch (getClz()) {
|
||||
switch (clz) {
|
||||
case ZI:
|
||||
return "I";
|
||||
case ZIFL:
|
||||
@ -260,23 +300,23 @@ public class TypeTransformer implements Transformer {
|
||||
}
|
||||
|
||||
public Set<String> getUses() {
|
||||
return t.getReal().uses;
|
||||
return getReal().uses;
|
||||
}
|
||||
|
||||
public String getProvideDesc() {
|
||||
return t.getReal().provideDesc;
|
||||
return getReal().provideDesc;
|
||||
}
|
||||
|
||||
public void setProvideDesc(String provideDesc) {
|
||||
this.t.getReal().provideDesc = provideDesc;
|
||||
this.getReal().provideDesc = provideDesc;
|
||||
}
|
||||
|
||||
public boolean addUses(String ele) {
|
||||
SharedT t=this.t.getReal();
|
||||
if (t.uses != null) {
|
||||
TypeRef t = this.getReal();
|
||||
if (uses != null) {
|
||||
return t.uses.add(ele);
|
||||
} else {
|
||||
t.uses = new HashSet<>();
|
||||
uses = new HashSet<>();
|
||||
return t.uses.add(ele);
|
||||
}
|
||||
}
|
||||
@ -309,24 +349,16 @@ public class TypeTransformer implements Transformer {
|
||||
private void fixTypes() {
|
||||
|
||||
// 1. collect all Array Roots
|
||||
UniqueQueue<TypeRef> q = new UniqueQueue<>();
|
||||
|
||||
Set<TypeRef> arrayRoots = new HashSet<>();
|
||||
for (TypeRef t : refs) {
|
||||
if (t.gArrayValues != null || t.sArrayValues != null) {
|
||||
arrayRoots.add(t);
|
||||
q.add(t);
|
||||
}
|
||||
}
|
||||
while (!q.isEmpty()) {
|
||||
TypeRef ref = q.poll();
|
||||
TypeRef.SharedT arrayValue=ref.getArrayValueShareT();
|
||||
if(ref.gArrayValues!=null){
|
||||
for(TypeRef t:ref.gArrayValues){
|
||||
|
||||
}
|
||||
for (TypeRef ref : refs) {
|
||||
if (ref.gArrayValues != null || ref.sArrayValues != null) {
|
||||
arrayRoots.add(ref);
|
||||
}
|
||||
ref.linkArray();
|
||||
}
|
||||
|
||||
UniqueQueue<TypeRef> q = new UniqueQueue<>();
|
||||
q.addAll(refs);
|
||||
while (!q.isEmpty()) {
|
||||
// 2. merge provided type to children. merge uses to parent. merge TypeClass to sameValues
|
||||
@ -364,25 +396,28 @@ public class TypeTransformer implements Transformer {
|
||||
}
|
||||
|
||||
private static void mergeTypeToArrayGetValue(String type, TypeRef target, UniqueQueue<TypeRef> q) {
|
||||
if (target.getProvideDesc() == null) {
|
||||
target.setProvideDesc(type);
|
||||
target = target.getReal();
|
||||
if (target.provideDesc == null) {
|
||||
target.provideDesc = type;
|
||||
q.add(target);
|
||||
} else {
|
||||
String mergedType = mergeTypeEx(type, target.getProvideDesc());
|
||||
if (!mergedType.equals(target.getProvideDesc())) {
|
||||
target.setProvideDesc(mergedType);
|
||||
String mergedType = mergeTypeEx(type, target.provideDesc);
|
||||
if (!mergedType.equals(target.provideDesc)) {
|
||||
target.provideDesc = mergedType;
|
||||
q.add(target);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void mergeTypeToSubRef(String type, TypeRef target, UniqueQueue<TypeRef> q) {
|
||||
if (target.getProvideDesc() == null) {
|
||||
target.setProvideDesc(type);
|
||||
target = target.getReal();
|
||||
if (target.provideDesc == null) {
|
||||
target.provideDesc = type;
|
||||
q.add(target);
|
||||
} else {
|
||||
String mergedType = mergeProviderType(type, target.getProvideDesc());
|
||||
if (!mergedType.equals(target.getProvideDesc())) {
|
||||
target.setProvideDesc(mergedType);
|
||||
String mergedType = mergeProviderType(type, target.provideDesc);
|
||||
if (!mergedType.equals(target.provideDesc)) {
|
||||
target.provideDesc = mergedType;
|
||||
q.add(target);
|
||||
}
|
||||
}
|
||||
@ -927,7 +962,10 @@ public class TypeTransformer implements Transformer {
|
||||
root.gArrayValues = new HashSet<>(3);
|
||||
}
|
||||
root.gArrayValues.add(value);
|
||||
value.arrayRoot = root;
|
||||
if (value.arrayRoots == null) {
|
||||
value.arrayRoots = new HashSet<>(3);
|
||||
}
|
||||
value.arrayRoots.add(root);
|
||||
}
|
||||
|
||||
private void linkSetArray(Value array, Value v) {
|
||||
@ -937,7 +975,10 @@ public class TypeTransformer implements Transformer {
|
||||
root.sArrayValues = new HashSet<>(3);
|
||||
}
|
||||
root.sArrayValues.add(value);
|
||||
value.arrayRoot = root;
|
||||
if (value.arrayRoots == null) {
|
||||
value.arrayRoots = new HashSet<>(3);
|
||||
}
|
||||
value.arrayRoots.add(root);
|
||||
}
|
||||
|
||||
private void linkFromTo(Value from, Value to) {
|
||||
@ -954,8 +995,8 @@ public class TypeTransformer implements Transformer {
|
||||
}
|
||||
|
||||
private void provideAs(Value op, String type) {
|
||||
TypeRef typeRef = getDefTypeRef(op);
|
||||
typeRef.setProvideDesc(type);
|
||||
TypeRef typeRef = getDefTypeRef(op).getReal();
|
||||
typeRef.provideDesc = (type);
|
||||
typeRef.updateTypeClass(TypeClass.clzOf(type));
|
||||
}
|
||||
|
||||
|
29
dex-translator/src/test/java/res/Gh28Type.java
Normal file
29
dex-translator/src/test/java/res/Gh28Type.java
Normal file
@ -0,0 +1,29 @@
|
||||
package res;
|
||||
|
||||
import java.lang.reflect.Array;
|
||||
|
||||
/**
|
||||
* https://github.com/pxb1988/dex2jar/issues/28
|
||||
*/
|
||||
public class Gh28Type {
|
||||
|
||||
protected void onCreate() {
|
||||
double t0[] = new double[1];
|
||||
t0[0] = 0;
|
||||
double t1[] = (double[]) Array.newInstance(Double.TYPE, 1);
|
||||
t1[0] = 0;
|
||||
double t2[][] = new double[1][1];
|
||||
t2[0][0] = 0; // incorrectly translated to 0L (long) rather than 0.0 (double)
|
||||
double t3[][] = (double[][]) Array.newInstance(Double.TYPE, 1, 1);
|
||||
t3[0][0] = 0; // incorrectly translated to 0L (long) rather than 0.0 (double)
|
||||
a(t0);
|
||||
a(t1);
|
||||
a(t2[0]);
|
||||
a(t3[0]);
|
||||
}
|
||||
|
||||
private void a(double[] t0) {
|
||||
// Just to avoid optimization of unused local variables in onCreate here above
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue
Block a user