Skip to content

Commit

Permalink
Merge pull request #2108 from MarcMil/fixes
Browse files Browse the repository at this point in the history
Fixes for Dex typing
  • Loading branch information
StevenArzt authored Oct 9, 2024
2 parents 87e8821 + 9301f8b commit 2ccab98
Show file tree
Hide file tree
Showing 19 changed files with 198 additions and 62 deletions.
96 changes: 93 additions & 3 deletions src/main/java/soot/dexpler/DexBody.java
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@

import soot.Body;
import soot.DoubleType;
import soot.FloatType;
import soot.Local;
import soot.LongType;
import soot.Modifier;
Expand All @@ -78,6 +79,7 @@
import soot.Trap;
import soot.Type;
import soot.Unit;
import soot.UnitPatchingChain;
import soot.UnknownType;
import soot.Value;
import soot.ValueBox;
Expand All @@ -88,18 +90,25 @@
import soot.dexpler.instructions.OdexInstruction;
import soot.dexpler.instructions.PseudoInstruction;
import soot.dexpler.instructions.RetypeableInstruction;
import soot.dexpler.tags.DexplerTag;
import soot.dexpler.tags.DoubleOpTag;
import soot.dexpler.tags.FloatOpTag;
import soot.dexpler.typing.DalvikTyper;
import soot.jimple.AssignStmt;
import soot.jimple.BinopExpr;
import soot.jimple.CastExpr;
import soot.jimple.CaughtExceptionRef;
import soot.jimple.ConditionExpr;
import soot.jimple.Constant;
import soot.jimple.DefinitionStmt;
import soot.jimple.DoubleConstant;
import soot.jimple.EqExpr;
import soot.jimple.FloatConstant;
import soot.jimple.IfStmt;
import soot.jimple.IntConstant;
import soot.jimple.Jimple;
import soot.jimple.JimpleBody;
import soot.jimple.LongConstant;
import soot.jimple.NeExpr;
import soot.jimple.NullConstant;
import soot.jimple.NumericConstant;
Expand All @@ -121,9 +130,11 @@
import soot.options.Options;
import soot.tagkit.LineNumberTag;
import soot.tagkit.SourceLineNumberTag;
import soot.tagkit.Tag;
import soot.toolkits.exceptions.TrapTightener;
import soot.toolkits.scalar.LocalPacker;
import soot.toolkits.scalar.LocalSplitter;
import soot.toolkits.scalar.SharedInitializationLocalSplitter;
import soot.toolkits.scalar.UnusedLocalEliminator;

/**
Expand Down Expand Up @@ -477,7 +488,6 @@ public DexlibAbstractInstruction instructionAtAddress(int address) {
* the SootMethod that contains this body
*/
public Body jimplify(Body b, SootMethod m) {

final Jimple jimple = Jimple.v();
final UnknownType unknownType = UnknownType.v();
final NullConstant nullConstant = NullConstant.v();
Expand Down Expand Up @@ -686,6 +696,8 @@ public Body jimplify(Body b, SootMethod m) {
// Make sure that we don't have any overlapping uses due to returns
DexReturnInliner.v().transform(jBody);

new SharedInitializationLocalSplitter(DalvikThrowAnalysis.v()).transform(jBody);

// split first to find undefined uses
getLocalSplitter().transform(jBody);

Expand Down Expand Up @@ -772,6 +784,8 @@ public Body jimplify(Body b, SootMethod m) {
}
DexFillArrayDataTransformer.v().transform(jBody);

convertFloatsAndDoubles(b, jimple);

TypeAssigner.v().transform(jBody);

// Shortcut: Reduce array initializations
Expand Down Expand Up @@ -932,6 +946,7 @@ public Body jimplify(Body b, SootMethod m) {
DexReturnPacker.v().transform(jBody);

for (Unit u : jBody.getUnits()) {

if (u instanceof AssignStmt) {
AssignStmt ass = (AssignStmt) u;
if (ass.getRightOp() instanceof CastExpr) {
Expand All @@ -946,7 +961,8 @@ public Body jimplify(Body b, SootMethod m) {
// If the body references a phantom class in a
// CaughtExceptionRef,
// we must manually fix the hierarchy
if (def.getLeftOp() instanceof Local && def.getRightOp() instanceof CaughtExceptionRef) {
Value rop = def.getRightOp();
if (def.getLeftOp() instanceof Local && rop instanceof CaughtExceptionRef) {
Type t = def.getLeftOp().getType();
if (t instanceof RefType) {
RefType rt = (RefType) t;
Expand All @@ -957,6 +973,7 @@ public Body jimplify(Body b, SootMethod m) {
}
}
}
removeDexplerTags(u);
}

// Replace local type null_type by java.lang.Object.
Expand Down Expand Up @@ -986,8 +1003,80 @@ public Body jimplify(Body b, SootMethod m) {
return jBody;
}

public void convertFloatsAndDoubles(Body b, final Jimple jimple) {
UnitPatchingChain units = jBody.getUnits();
Unit u = units.getFirst();
Local[] convFloat = new Local[2], convDouble = new Local[2];

while (u != null) {
if (u instanceof AssignStmt) {
AssignStmt def = (AssignStmt) u;
Value rop = def.getRightOp();
if (rop instanceof BinopExpr) {
boolean isDouble = u.hasTag(DoubleOpTag.NAME);
boolean isFloat = u.hasTag(FloatOpTag.NAME);
BinopExpr bop = (BinopExpr) rop;
int idxConvVar = 0;
for (ValueBox cmp : bop.getUseBoxes()) {
Value c = cmp.getValue();
if (c instanceof Constant) {
if (isDouble) {
if (c instanceof LongConstant) {
long vVal = ((LongConstant) c).value;
cmp.setValue(DoubleConstant.v(Double.longBitsToDouble(vVal)));
}
} else if (isFloat && c instanceof IntConstant) {
int vVal = ((IntConstant) c).value;
cmp.setValue(FloatConstant.v(Float.intBitsToFloat(vVal)));
}
} else {
if (isDouble) {
if (!(c.getType() instanceof DoubleType)) {
if (convDouble[idxConvVar] == null) {
convDouble[idxConvVar] = jimple.newLocal("lclConvToDouble" + idxConvVar, DoubleType.v());
b.getLocals().add(convDouble[idxConvVar]);
}
units.insertBefore(
jimple.newAssignStmt(convDouble[idxConvVar], jimple.newCastExpr(cmp.getValue(), DoubleType.v())), u);
cmp.setValue(convDouble[idxConvVar]);
idxConvVar++;
}
} else if (isFloat) {
if (!(c.getType() instanceof FloatType)) {
if (convFloat[idxConvVar] == null) {
convFloat[idxConvVar] = jimple.newLocal("lclConvToFloat" + idxConvVar, FloatType.v());
b.getLocals().add(convFloat[idxConvVar]);
}
units.insertBefore(
jimple.newAssignStmt(convFloat[idxConvVar], jimple.newCastExpr(cmp.getValue(), FloatType.v())), u);
cmp.setValue(convFloat[idxConvVar]);
idxConvVar++;
}
}
}
}
}

}
u = units.getSuccOf(u);
}
}

/**
* Removes all dexpler specific tags. Saves some memory.
* @param unit the statement
*/
private void removeDexplerTags(Unit unit) {
for (Tag t : unit.getTags()) {
if (t instanceof DexplerTag) {
unit.removeTag(t.getName());
}

}
}

/**
* Checks wheter the Jimple code contains unrealizable casts between reference types and primitives
* Checks whether the Jimple code contains unrealizable casts between reference types and primitives
*/
private void checkUnrealizableCasts() {
for (Unit u : jBody.getUnits()) {
Expand All @@ -998,6 +1087,7 @@ private void checkUnrealizableCasts() {
CastExpr cast = (CastExpr) rop;
if ((cast.getCastType() instanceof PrimType && cast.getOp().getType() instanceof RefType)
|| (cast.getCastType() instanceof RefType && cast.getOp().getType() instanceof PrimType)) {

throw new RuntimeException("Unrealizable cast " + u + " detected in method " + jBody.getMethod().getSignature());
}
}
Expand Down
9 changes: 7 additions & 2 deletions src/main/java/soot/dexpler/DexNullThrowTransformer.java
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@

import soot.Body;
import soot.BodyTransformer;
import soot.BooleanConstant;
import soot.Local;
import soot.RefType;
import soot.Scene;
Expand Down Expand Up @@ -64,14 +65,18 @@ public static DexNullThrowTransformer v() {
protected void internalTransform(Body b, String phaseName, Map<String, String> options) {
LocalCreation lc = Scene.v().createLocalCreation(b.getLocals(), "ex");

final NullConstant nc = NullConstant.v();
final IntConstant ic = IntConstant.v(0);
final BooleanConstant bc = BooleanConstant.v(false);
final LongConstant llc = LongConstant.v(0);
for (Iterator<Unit> unitIt = b.getUnits().snapshotIterator(); unitIt.hasNext();) {
Unit u = unitIt.next();

// Check for a null exception
if (u instanceof ThrowStmt) {
ThrowStmt throwStmt = (ThrowStmt) u;
if (throwStmt.getOp() == NullConstant.v() || throwStmt.getOp().equals(IntConstant.v(0))
|| throwStmt.getOp().equals(LongConstant.v(0))) {
if (throwStmt.getOp() == nc || throwStmt.getOp().equals(ic) || throwStmt.getOp().equals(llc)
|| throwStmt.getOp().equals(bc)) {
createThrowStmt(b, throwStmt, lc);
}
}
Expand Down
27 changes: 7 additions & 20 deletions src/main/java/soot/dexpler/DexNullTransformer.java
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,6 @@ public void caseAssignStmt(AssignStmt stmt) {
if (r instanceof FieldRef) {
usedAsObject = isObject(((FieldRef) r).getFieldRef().type());
doBreak = true;
return;
} else if (r instanceof ArrayRef) {
ArrayRef ar = (ArrayRef) r;
if (ar.getType() instanceof UnknownType) {
Expand All @@ -117,24 +116,19 @@ public void caseAssignStmt(AssignStmt stmt) {
usedAsObject = isObject(ar.getType());
}
doBreak = true;
return;
} else if (r instanceof StringConstant || r instanceof NewExpr || r instanceof NewArrayExpr
|| r instanceof ClassConstant) {
usedAsObject = true;
doBreak = true;
return;
} else if (r instanceof CastExpr) {
usedAsObject = isObject(((CastExpr) r).getCastType());
doBreak = true;
return;
} else if (r instanceof InvokeExpr) {
usedAsObject = isObject(((InvokeExpr) r).getType());
doBreak = true;
return;
} else if (r instanceof LengthExpr) {
usedAsObject = false;
doBreak = true;
return;
// introduces alias
}

Expand Down Expand Up @@ -221,15 +215,14 @@ public void caseAssignStmt(AssignStmt stmt) {
} else if (l instanceof ArrayRef) {
Type aType = ((ArrayRef) l).getType();
if (aType instanceof UnknownType) {
usedAsObject = stmt.hasTag(ObjectOpTag.NAME); // isObject(
// findArrayType(g,
// localDefs,
// localUses,
// stmt));
if (stmt.hasTag(ObjectOpTag.NAME)) {
usedAsObject = true;
doBreak = true;
}
} else {
usedAsObject = isObject(aType);
doBreak = true;
}
doBreak = true;
return;
}
}
Expand All @@ -239,7 +232,6 @@ public void caseAssignStmt(AssignStmt stmt) {
usedAsObject = true; // isObject(((FieldRef)
// r).getFieldRef().type());
doBreak = true;
return;
} else if (r instanceof ArrayRef) {
ArrayRef ar = (ArrayRef) r;
if (ar.getBase() == l) {
Expand All @@ -248,29 +240,24 @@ public void caseAssignStmt(AssignStmt stmt) {
usedAsObject = false;
}
doBreak = true;
return;
} else if (r instanceof StringConstant || r instanceof NewExpr) {
throw new RuntimeException("NOT POSSIBLE StringConstant or NewExpr at " + stmt);
usedAsObject = true;
doBreak = true;
} else if (r instanceof NewArrayExpr) {
usedAsObject = false;
doBreak = true;
return;
} else if (r instanceof CastExpr) {
usedAsObject = isObject(((CastExpr) r).getCastType());
doBreak = true;
return;
} else if (r instanceof InvokeExpr) {
usedAsObject = examineInvokeExpr((InvokeExpr) stmt.getRightOp());
doBreak = true;
return;
} else if (r instanceof LengthExpr) {
usedAsObject = true;
doBreak = true;
return;
} else if (r instanceof BinopExpr) {
usedAsObject = false;
doBreak = true;
return;
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,6 @@

import soot.Local;
import soot.dexpler.DexBody;
import soot.dexpler.DexFillArrayDataTransformer;
import soot.dexpler.typing.UntypedConstant;
import soot.dexpler.typing.UntypedIntOrFloatConstant;
import soot.dexpler.typing.UntypedLongOrDoubleConstant;
import soot.jimple.ArrayRef;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,12 @@

import soot.ArrayType;
import soot.Local;
import soot.RefLikeType;
import soot.Type;
import soot.dexpler.DexBody;
import soot.dexpler.DexType;
import soot.dexpler.IDalvikTyper;
import soot.dexpler.tags.ObjectOpTag;
import soot.dexpler.typing.DalvikTyper;
import soot.jimple.ArrayRef;
import soot.jimple.AssignStmt;
Expand Down Expand Up @@ -68,8 +70,8 @@ public void jimplify(DexBody body) {

Type t = DexType.toSoot((TypeReference) filledNewArrayInstr.getReference());
// NewArrayExpr needs the ElementType as it increases the array dimension by 1
Type arrayType = ((ArrayType) t).getElementType();
NewArrayExpr arrayExpr = Jimple.v().newNewArrayExpr(arrayType, IntConstant.v(usedRegister));
Type elementType = ((ArrayType) t).getElementType();
NewArrayExpr arrayExpr = Jimple.v().newNewArrayExpr(elementType, IntConstant.v(usedRegister));
// new local generated intentional, will be moved to real register by MoveResult
Local arrayLocal = body.getStoreResultLocal();
AssignStmt assign = Jimple.v().newAssignStmt(arrayLocal, arrayExpr);
Expand All @@ -78,6 +80,9 @@ public void jimplify(DexBody body) {
ArrayRef arrayRef = Jimple.v().newArrayRef(arrayLocal, IntConstant.v(i));

AssignStmt assign2 = Jimple.v().newAssignStmt(arrayRef, body.getRegisterLocal(regs[i]));
if (elementType instanceof RefLikeType) {
assign2.addTag(new ObjectOpTag());
}
addTags(assign2);
body.add(assign2);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,12 @@

import soot.ArrayType;
import soot.Local;
import soot.RefLikeType;
import soot.Type;
import soot.dexpler.DexBody;
import soot.dexpler.DexType;
import soot.dexpler.IDalvikTyper;
import soot.dexpler.tags.ObjectOpTag;
import soot.dexpler.typing.DalvikTyper;
import soot.jimple.ArrayRef;
import soot.jimple.AssignStmt;
Expand Down Expand Up @@ -66,8 +68,8 @@ public void jimplify(DexBody body) {
int usedRegister = filledNewArrayInstr.getRegisterCount();
Type t = DexType.toSoot((TypeReference) filledNewArrayInstr.getReference());
// NewArrayExpr needs the ElementType as it increases the array dimension by 1
Type arrayType = ((ArrayType) t).getElementType();
NewArrayExpr arrayExpr = Jimple.v().newNewArrayExpr(arrayType, IntConstant.v(usedRegister));
Type elementType = ((ArrayType) t).getElementType();
NewArrayExpr arrayExpr = Jimple.v().newNewArrayExpr(elementType, IntConstant.v(usedRegister));
Local arrayLocal = body.getStoreResultLocal();
AssignStmt assignStmt = Jimple.v().newAssignStmt(arrayLocal, arrayExpr);
body.add(assignStmt);
Expand All @@ -77,6 +79,9 @@ public void jimplify(DexBody body) {

AssignStmt assign
= Jimple.v().newAssignStmt(arrayRef, body.getRegisterLocal(i + filledNewArrayInstr.getStartRegister()));
if (elementType instanceof RefLikeType) {
assign.addTag(new ObjectOpTag());
}
addTags(assign);
body.add(assign);
}
Expand Down
Loading

0 comments on commit 2ccab98

Please sign in to comment.