
crypto.preanalysis.UpdatedBoomerangPreTransformer Maven / Gradle / Ivy
package crypto.preanalysis;
import com.google.common.collect.Sets;
import java.util.AbstractMap;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import soot.Body;
import soot.Local;
import soot.RefType;
import soot.SootField;
import soot.SootMethod;
import soot.Unit;
import soot.UnitPatchingChain;
import soot.Value;
import soot.ValueBox;
import soot.jimple.ArrayRef;
import soot.jimple.AssignStmt;
import soot.jimple.ClassConstant;
import soot.jimple.Constant;
import soot.jimple.IdentityStmt;
import soot.jimple.IfStmt;
import soot.jimple.InstanceFieldRef;
import soot.jimple.NullConstant;
import soot.jimple.ReturnStmt;
import soot.jimple.StaticFieldRef;
import soot.jimple.Stmt;
import soot.jimple.internal.JAssignStmt;
import soot.jimple.internal.JInstanceFieldRef;
import soot.jimple.internal.JNopStmt;
import soot.jimple.internal.JReturnStmt;
import soot.jimple.internal.JimpleLocal;
import soot.tagkit.AttributeValueException;
import soot.tagkit.LineNumberTag;
import soot.tagkit.SourceLnPosTag;
import soot.tagkit.Tag;
import soot.util.Chain;
public class UpdatedBoomerangPreTransformer extends PreTransformer {
public static boolean TRANSFORM_CONSTANTS = true;
public static String UNINITIALIZED_FIELD_TAG_NAME = "UninitializedField";
public static Tag UNITIALIZED_FIELD_TAG =
new Tag() {
@Override
public String getName() {
return UNINITIALIZED_FIELD_TAG_NAME;
}
@Override
public byte[] getValue() throws AttributeValueException {
return new byte[0];
}
};
private static UpdatedBoomerangPreTransformer instance;
private int replaceCounter;
@Override
protected void internalTransform(Body b, String phaseName, Map options) {
if (b.getMethod().isConstructor()) {
addNulliefiedFields(b.getMethod());
}
addNopStmtToMethods(b);
if (TRANSFORM_CONSTANTS) {
transformConstantAtFieldWrites(b);
}
}
private void transformConstantAtFieldWrites(Body body) {
Set cwnc = getStmtsWithConstants(body);
for (Unit u : cwnc) {
if (u instanceof AssignStmt) {
AssignStmt assignStmt = (AssignStmt) u;
if (isFieldRef(assignStmt.getLeftOp())
&& assignStmt.getRightOp() instanceof Constant
&& !(assignStmt.getRightOp() instanceof ClassConstant)) {
String label = "varReplacer" + replaceCounter++;
Local paramVal = new JimpleLocal(label, assignStmt.getRightOp().getType());
AssignStmt newUnit = new JAssignStmt(paramVal, assignStmt.getRightOp());
body.getLocals().add(paramVal);
body.getUnits().insertBefore(newUnit, u);
AssignStmt other = new JAssignStmt(assignStmt.getLeftOp(), paramVal);
other.addAllTagsOf(u);
body.getUnits().insertBefore(other, u);
body.getUnits().remove(u);
}
}
if (u instanceof Stmt
&& ((Stmt) u).containsInvokeExpr()
&& !u.toString().contains("test.assertions.Assertions:")
&& !u.toString().contains("intQueryFor")) {
Stmt stmt = (Stmt) u;
List useBoxes = stmt.getInvokeExpr().getUseBoxes();
List> newArgs = new ArrayList<>();
for (int i = 0; i < stmt.getInvokeExpr().getArgs().size(); i++) {
Value v = stmt.getInvokeExpr().getArg(i);
if (v instanceof Constant && !(v instanceof ClassConstant)) {
String label = "varReplacer" + replaceCounter++;
Local paramVal = new JimpleLocal(label, v.getType());
AssignStmt newUnit = new JAssignStmt(paramVal, v);
newUnit.addAllTagsOf(u);
body.getLocals().add(paramVal);
body.getUnits().insertBefore(newUnit, u);
for (ValueBox b : useBoxes) {
backPropagateSourceLineTags(b, newUnit);
}
Map.Entry entry =
new AbstractMap.SimpleEntry<>(i, paramVal);
newArgs.add(entry);
}
}
// Update the parameters
for (Map.Entry entry : newArgs) {
int position = entry.getKey();
Value newArg = entry.getValue();
stmt.getInvokeExpr().setArg(position, newArg);
}
}
if (u instanceof ReturnStmt) {
ReturnStmt returnStmt = (ReturnStmt) u;
String label = "varReplacer" + replaceCounter++;
Local paramVal = new JimpleLocal(label, returnStmt.getOp().getType());
AssignStmt newUnit = new JAssignStmt(paramVal, returnStmt.getOp());
newUnit.addAllTagsOf(u);
body.getLocals().add(paramVal);
body.getUnits().insertBefore(newUnit, u);
JReturnStmt other = new JReturnStmt(paramVal);
body.getUnits().insertBefore(other, u);
body.getUnits().remove(u);
}
}
}
/**
* Propagates back the line number tags from the constant value box to the newly created
* AssignStmt, to revert the forward propagation done in {@link
* soot.jimple.toolkits.scalar.CopyPropagator}
*
* @param valueBox the constant value box
* @param assignStmt the corresponding assign statement
*/
private void backPropagateSourceLineTags(ValueBox valueBox, AssignStmt assignStmt) {
Tag tag = valueBox.getTag(SourceLnPosTag.NAME);
if (tag != null) {
// in case that we copied a line number tag from the original statement, we want to
// remove
// that now since the valueBox contains the correct lin number tag for the assign
// statement as
// it was before copy propagation
assignStmt.removeTag(SourceLnPosTag.NAME);
assignStmt.addTag(tag);
}
tag = valueBox.getTag(LineNumberTag.NAME);
if (tag != null) {
// same as for the above case
assignStmt.removeTag(LineNumberTag.NAME);
assignStmt.addTag(tag);
}
}
/**
* The first statement of a method must be a nop statement, because the call-flow functions do
* only map parameters to arguments. If the first statement of a method would be an assign
* statement, the analysis misses data-flows.
*/
private void addNopStmtToMethods(Body b) {
JNopStmt nopStmt = new JNopStmt();
for (Unit u : b.getUnits()) {
if (u.getJavaSourceStartLineNumber() > 0) {
nopStmt.addAllTagsOf(u);
break;
}
}
b.getUnits().insertBefore(nopStmt, b.getUnits().getFirst());
Set ifStmts = Sets.newHashSet();
for (Unit u : b.getUnits()) {
if (u instanceof IfStmt) {
// ((IfStmt) u).getTarget();
ifStmts.add((IfStmt) u);
}
}
// After all if-stmts we add a nop-stmt to make the analysis
for (IfStmt ifStmt : ifStmts) {
nopStmt = new JNopStmt();
nopStmt.addAllTagsOf(ifStmt);
b.getUnits().insertAfter(nopStmt, ifStmt);
Unit target = ifStmt.getTarget();
nopStmt = new JNopStmt();
nopStmt.addAllTagsOf(target);
b.getUnits().insertBefore(nopStmt, target);
ifStmt.setTarget(nopStmt);
}
}
private Set getStmtsWithConstants(Body methodBody) {
Set retMap = Sets.newHashSet();
for (Unit u : methodBody.getUnits()) {
if (u instanceof AssignStmt) {
AssignStmt assignStmt = (AssignStmt) u;
if (isFieldRef(assignStmt.getLeftOp())
&& assignStmt.getRightOp() instanceof Constant) {
retMap.add(u);
}
}
if (u instanceof Stmt && ((Stmt) u).containsInvokeExpr()) {
Stmt stmt = (Stmt) u;
for (Value v : stmt.getInvokeExpr().getArgs()) {
if (v instanceof Constant) {
retMap.add(u);
}
}
}
if (u instanceof ReturnStmt) {
ReturnStmt assignStmt = (ReturnStmt) u;
if (assignStmt.getOp() instanceof Constant) {
retMap.add(u);
}
}
}
return retMap;
}
private boolean isFieldRef(Value op) {
return op instanceof InstanceFieldRef
|| op instanceof StaticFieldRef
|| op instanceof ArrayRef;
}
private static void addNulliefiedFields(SootMethod cons) {
Chain fields = cons.getDeclaringClass().getFields();
UnitPatchingChain units = cons.getActiveBody().getUnits();
Set fieldsDefinedInMethod = getFieldsDefinedInMethod(cons, Sets.newHashSet());
for (SootField f : fields) {
if (fieldsDefinedInMethod.contains(f)) continue;
if (f.isStatic()) continue;
if (f.isFinal()) continue;
if (f.getType() instanceof RefType) {
JAssignStmt jAssignStmt =
new JAssignStmt(
new JInstanceFieldRef(
cons.getActiveBody().getThisLocal(), f.makeRef()),
NullConstant.v());
jAssignStmt.addTag(new LineNumberTag(2));
jAssignStmt.addTag(UNITIALIZED_FIELD_TAG);
Unit lastIdentityStmt = findLastIdentityStmt(units);
if (lastIdentityStmt != null) {
units.insertAfter(jAssignStmt, lastIdentityStmt);
} else {
units.addFirst(jAssignStmt);
}
}
}
}
private static Unit findLastIdentityStmt(UnitPatchingChain units) {
for (Unit u : units) {
if (u instanceof IdentityStmt && u instanceof AssignStmt) {
continue;
}
return u;
}
return null;
}
private static Set getFieldsDefinedInMethod(
SootMethod cons, Set visited) {
Set res = Sets.newHashSet();
if (!visited.add(cons)) return res;
if (!cons.hasActiveBody()) return res;
for (Unit u : cons.getActiveBody().getUnits()) {
if (u instanceof AssignStmt) {
AssignStmt as = (AssignStmt) u;
Value left = as.getLeftOp();
if (left instanceof InstanceFieldRef) {
InstanceFieldRef ifr = (InstanceFieldRef) left;
res.add(ifr.getField());
}
}
if (u instanceof Stmt) {
Stmt stmt = (Stmt) u;
if (stmt.containsInvokeExpr()) {
if (stmt.getInvokeExpr().getMethod().isConstructor()) {
res.addAll(
getFieldsDefinedInMethod(
stmt.getInvokeExpr().getMethod(), visited));
}
}
}
}
return res;
}
public static UpdatedBoomerangPreTransformer v() {
if (instance == null) {
instance = new UpdatedBoomerangPreTransformer();
}
return instance;
}
public void reset() {
instance = null;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy