Search in sources :

Example 1 with ConflictingFieldRefException

use of soot.ConflictingFieldRefException in project soot by Sable.

the class ConstantInitializerToTagTransformer method transformClass.

/**
 * Transforms the given class, i.e. scans for a <clinit> method and
 * generates new constant value tags for all constant assignments to static
 * final fields.
 *
 * @param sc
 *            The class to transform
 * @param removeAssignments
 *            True if the assignments inside the <clinit> method shall be
 *            removed, otherwise false
 */
public void transformClass(SootClass sc, boolean removeAssignments) {
    // If this class has no <clinit> method, we're done
    SootMethod smInit = sc.getMethodByNameUnsafe("<clinit>");
    if (smInit == null || !smInit.isConcrete())
        return;
    Set<SootField> nonConstantFields = new HashSet<SootField>();
    Map<SootField, ConstantValueTag> newTags = new HashMap<SootField, ConstantValueTag>();
    // in case of
    Set<SootField> removeTagList = new HashSet<SootField>();
    for (Iterator<Unit> itU = smInit.getActiveBody().getUnits().snapshotIterator(); itU.hasNext(); ) {
        Unit u = itU.next();
        if (u instanceof AssignStmt) {
            AssignStmt assign = (AssignStmt) u;
            if (assign.getLeftOp() instanceof StaticFieldRef && assign.getRightOp() instanceof Constant) {
                SootField field = null;
                try {
                    field = ((StaticFieldRef) assign.getLeftOp()).getField();
                    if (field == null || nonConstantFields.contains(field))
                        continue;
                } catch (ConflictingFieldRefException ex) {
                    // Ignore this statement
                    continue;
                }
                if (field.getDeclaringClass().equals(sc) && field.isStatic() && field.isFinal()) {
                    // Do we already have a constant value for this field?
                    boolean found = false;
                    for (Tag t : field.getTags()) {
                        if (t instanceof ConstantValueTag) {
                            if (checkConstantValue((ConstantValueTag) t, (Constant) assign.getRightOp())) {
                                // the assignment.
                                if (removeAssignments)
                                    itU.remove();
                            } else {
                                logger.debug("" + "WARNING: Constant value for field '" + field + "' mismatch between code (" + assign.getRightOp() + ") and constant table (" + t + ")");
                                removeTagList.add(field);
                            }
                            found = true;
                            break;
                        }
                    }
                    if (!found) {
                        // tags.
                        if (!checkConstantValue(newTags.get(field), (Constant) assign.getRightOp())) {
                            nonConstantFields.add(field);
                            newTags.remove(field);
                            removeTagList.add(field);
                            continue;
                        }
                        ConstantValueTag newTag = createConstantTagFromValue((Constant) assign.getRightOp());
                        if (newTag != null)
                            newTags.put(field, newTag);
                    }
                }
            } else if (assign.getLeftOp() instanceof StaticFieldRef) {
                // a non-constant is assigned to the field
                try {
                    SootField sf = ((StaticFieldRef) assign.getLeftOp()).getField();
                    if (sf != null)
                        removeTagList.add(sf);
                } catch (ConflictingFieldRefException ex) {
                // let's assume that a broken field doesn't cause any
                // harm
                }
            }
        }
    }
    // Do the actual assignment
    for (Entry<SootField, ConstantValueTag> entry : newTags.entrySet()) {
        SootField field = entry.getKey();
        if (removeTagList.contains(field))
            continue;
        field.addTag(entry.getValue());
    }
    if (removeAssignments && !newTags.isEmpty())
        for (Iterator<Unit> itU = smInit.getActiveBody().getUnits().snapshotIterator(); itU.hasNext(); ) {
            Unit u = itU.next();
            if (u instanceof AssignStmt) {
                AssignStmt assign = (AssignStmt) u;
                if (assign.getLeftOp() instanceof FieldRef)
                    try {
                        SootField fld = ((FieldRef) assign.getLeftOp()).getField();
                        if (fld != null && newTags.containsKey(fld))
                            itU.remove();
                    } catch (ConflictingFieldRefException ex) {
                    // Ignore broken code
                    }
            }
        }
    // remove constant tags
    for (SootField sf : removeTagList) {
        if (removeTagList.contains(sf)) {
            List<Tag> toRemoveTagList = new ArrayList<Tag>();
            for (Tag t : sf.getTags()) {
                if (t instanceof ConstantValueTag) {
                    toRemoveTagList.add(t);
                }
            }
            for (Tag t : toRemoveTagList) {
                sf.getTags().remove(t);
            }
        }
    }
}
Also used : FieldRef(soot.jimple.FieldRef) StaticFieldRef(soot.jimple.StaticFieldRef) HashMap(java.util.HashMap) AssignStmt(soot.jimple.AssignStmt) Constant(soot.jimple.Constant) LongConstant(soot.jimple.LongConstant) DoubleConstant(soot.jimple.DoubleConstant) IntConstant(soot.jimple.IntConstant) StringConstant(soot.jimple.StringConstant) FloatConstant(soot.jimple.FloatConstant) ArrayList(java.util.ArrayList) Unit(soot.Unit) ConflictingFieldRefException(soot.ConflictingFieldRefException) StaticFieldRef(soot.jimple.StaticFieldRef) ConstantValueTag(soot.tagkit.ConstantValueTag) DoubleConstantValueTag(soot.tagkit.DoubleConstantValueTag) FloatConstantValueTag(soot.tagkit.FloatConstantValueTag) IntegerConstantValueTag(soot.tagkit.IntegerConstantValueTag) StringConstantValueTag(soot.tagkit.StringConstantValueTag) LongConstantValueTag(soot.tagkit.LongConstantValueTag) Iterator(java.util.Iterator) SootMethod(soot.SootMethod) SootField(soot.SootField) Tag(soot.tagkit.Tag) ConstantValueTag(soot.tagkit.ConstantValueTag) DoubleConstantValueTag(soot.tagkit.DoubleConstantValueTag) FloatConstantValueTag(soot.tagkit.FloatConstantValueTag) IntegerConstantValueTag(soot.tagkit.IntegerConstantValueTag) StringConstantValueTag(soot.tagkit.StringConstantValueTag) LongConstantValueTag(soot.tagkit.LongConstantValueTag) HashSet(java.util.HashSet)

Aggregations

ArrayList (java.util.ArrayList)1 HashMap (java.util.HashMap)1 HashSet (java.util.HashSet)1 Iterator (java.util.Iterator)1 ConflictingFieldRefException (soot.ConflictingFieldRefException)1 SootField (soot.SootField)1 SootMethod (soot.SootMethod)1 Unit (soot.Unit)1 AssignStmt (soot.jimple.AssignStmt)1 Constant (soot.jimple.Constant)1 DoubleConstant (soot.jimple.DoubleConstant)1 FieldRef (soot.jimple.FieldRef)1 FloatConstant (soot.jimple.FloatConstant)1 IntConstant (soot.jimple.IntConstant)1 LongConstant (soot.jimple.LongConstant)1 StaticFieldRef (soot.jimple.StaticFieldRef)1 StringConstant (soot.jimple.StringConstant)1 ConstantValueTag (soot.tagkit.ConstantValueTag)1 DoubleConstantValueTag (soot.tagkit.DoubleConstantValueTag)1 FloatConstantValueTag (soot.tagkit.FloatConstantValueTag)1