Beispiel #1
0
 public static String getDescriptor(soot.Type t) {
   if (t instanceof PrimType) {
     if (t.equals(BooleanType.v())) {
       return "Z";
     } else if (t.equals(ByteType.v())) {
       return "B";
     } else if (t.equals(ShortType.v())) {
       return "S";
     } else if (t.equals(CharType.v())) {
       return "C";
     } else if (t.equals(IntType.v())) {
       return "I";
     } else if (t.equals(LongType.v())) {
       return "J";
     } else if (t.equals(FloatType.v())) {
       return "F";
     } else {
       // DoubleType
       return "D";
     }
   } else if (t.equals(VoidType.v())) {
     return "V";
   } else if (t instanceof soot.ArrayType) {
     soot.ArrayType at = (soot.ArrayType) t;
     return "[" + getDescriptor(at.getElementType());
   } else {
     // RefType
     RefType rt = (RefType) t;
     return "L" + rt.getClassName().replace('.', '/') + ";";
   }
 }
Beispiel #2
0
 public static Type getType(soot.Type sootType) {
   if (sootType.equals(soot.BooleanType.v())) {
     return Type.I8;
   } else if (sootType.equals(soot.ByteType.v())) {
     return Type.I8;
   } else if (sootType.equals(soot.ShortType.v())) {
     return Type.I16;
   } else if (sootType.equals(soot.CharType.v())) {
     return Type.I16;
   } else if (sootType.equals(soot.IntType.v())) {
     return Type.I32;
   } else if (sootType.equals(soot.LongType.v())) {
     return Type.I64;
   } else if (sootType.equals(soot.FloatType.v())) {
     return Type.FLOAT;
   } else if (sootType.equals(soot.DoubleType.v())) {
     return Type.DOUBLE;
   } else if (sootType.equals(soot.VoidType.v())) {
     return Type.VOID;
   } else if (sootType instanceof soot.RefLikeType || sootType.equals(BottomType.v())) {
     return OBJECT_PTR;
   } else {
     throw new IllegalArgumentException("Unknown Type: " + sootType);
   }
 }
Beispiel #3
0
 public static int getFieldSize(Arch arch, SootField f) {
   soot.Type t = f.getType();
   if (LongType.v().equals(t) || DoubleType.v().equals(t)) {
     return 8;
   }
   if (IntType.v().equals(t) || FloatType.v().equals(t)) {
     return 4;
   }
   if (t instanceof RefLikeType) {
     return arch.is32Bit() ? 4 : 8;
   }
   if (ShortType.v().equals(t) || CharType.v().equals(t)) {
     return 2;
   }
   if (ByteType.v().equals(t) || BooleanType.v().equals(t)) {
     return 1;
   }
   throw new IllegalArgumentException("Unknown Type: " + t);
 }
Beispiel #4
0
 private static int getFieldSize(SootField f) {
   soot.Type t = f.getType();
   if (LongType.v().equals(t) || DoubleType.v().equals(t)) {
     return 8;
   }
   if (IntType.v().equals(t) || FloatType.v().equals(t)) {
     return 4;
   }
   if (t instanceof RefLikeType) {
     // Assume pointers are 32-bit
     return 4;
   }
   if (ShortType.v().equals(t) || CharType.v().equals(t)) {
     return 2;
   }
   if (ByteType.v().equals(t) || BooleanType.v().equals(t)) {
     return 1;
   }
   throw new IllegalArgumentException("Unknown Type: " + t);
 }
Beispiel #5
0
/** A register for the Dalvik VM. It has a number and a type. */
public class Register implements Cloneable {

  public static final int MAX_REG_NUM_UNCONSTRAINED = 65535;

  public static final int MAX_REG_NUM_SHORT = 255;

  public static final int MAX_REG_NUM_BYTE = 15;

  public static final Register EMPTY_REGISTER = new Register(IntType.v(), 0);

  private static boolean fitsInto(int regNumber, int maxNumber, boolean isWide) {
    if (isWide) {
      // reg occupies number and number + 1, hence the "<"
      return regNumber >= 0 && regNumber < maxNumber;
    }
    return regNumber >= 0 && regNumber <= maxNumber;
  }

  public static boolean fitsUnconstrained(int regNumber, boolean isWide) {
    return fitsInto(regNumber, MAX_REG_NUM_UNCONSTRAINED, isWide);
  }

  public static boolean fitsShort(int regNumber, boolean isWide) {
    return fitsInto(regNumber, MAX_REG_NUM_SHORT, isWide);
  }

  public static boolean fitsByte(int regNumber, boolean isWide) {
    return fitsInto(regNumber, MAX_REG_NUM_BYTE, isWide);
  }

  private final Type type;

  private int number;

  public Register(Type type, int number) {
    this.type = type;
    this.number = number;
  }

  public boolean isEmptyReg() {
    return this == EMPTY_REGISTER;
  }

  public boolean isWide() {
    return SootToDexUtils.isWide(type);
  }

  public boolean isObject() {
    return SootToDexUtils.isObject(type);
  }

  public boolean isFloat() {
    return type instanceof FloatType;
  }

  public boolean isDouble() {
    return type instanceof DoubleType;
  }

  public Type getType() {
    return type;
  }

  public String getTypeString() {
    return type.toString();
  }

  public int getNumber() {
    return number;
  }

  public void setNumber(int number) {
    if (isEmptyReg()) {
      // number of empty register stays at zero - that's part of its purpose
      return;
    }
    this.number = number;
  }

  private boolean fitsInto(int maxNumber) {
    if (isEmptyReg()) {
      // empty reg fits into anything
      return true;
    }
    return fitsInto(number, maxNumber, isWide());
  }

  public boolean fitsUnconstrained() {
    return fitsInto(MAX_REG_NUM_UNCONSTRAINED);
  }

  public boolean fitsShort() {
    return fitsInto(MAX_REG_NUM_SHORT);
  }

  public boolean fitsByte() {
    return fitsInto(MAX_REG_NUM_BYTE);
  }

  @Override
  public Register clone() {
    return new Register(this.type, this.number);
  }

  @Override
  public String toString() {
    if (isEmptyReg()) {
      return "the empty reg";
    }
    return "reg(" + number + "):" + type.toString();
  }

  @Override
  public int hashCode() {
    final int prime = 31;
    int result = 1;
    result = prime * result + number;
    result = prime * result + ((type == null) ? 0 : type.hashCode());
    return result;
  }

  @Override
  public boolean equals(Object obj) {
    if (this == obj) return true;
    if (obj == null) return false;
    if (getClass() != obj.getClass()) return false;
    Register other = (Register) obj;
    if (number != other.number) return false;
    if (type == null) {
      if (other.type != null) return false;
    } else if (!type.equals(other.type)) return false;
    return true;
  }
}
Beispiel #6
0
 public void outAIntBaseType(AIntBaseType node) {
   mProductions.addLast(IntType.v());
 }
Beispiel #7
0
 /** @apilevel internal */
 private Type getSootType_compute() {
   return soot.IntType.v();
 }
Beispiel #8
0
  private StructureConstant createClassInfoStruct() {
    int flags = 0;

    if (Modifier.isPublic(sootClass.getModifiers())) {
      flags |= CI_PUBLIC;
    }
    if (Modifier.isFinal(sootClass.getModifiers())) {
      flags |= CI_FINAL;
    }
    if (Modifier.isInterface(sootClass.getModifiers())) {
      flags |= CI_INTERFACE;
    }
    if (Modifier.isAbstract(sootClass.getModifiers())) {
      flags |= CI_ABSTRACT;
    }
    if ((sootClass.getModifiers() & 0x1000) > 0) {
      flags |= CI_SYNTHETIC;
    }
    if (Modifier.isAnnotation(sootClass.getModifiers())) {
      flags |= CI_ANNOTATION;
    }
    if (Modifier.isEnum(sootClass.getModifiers())) {
      flags |= CI_ENUM;
    }
    if (attributesEncoder.classHasAttributes()) {
      flags |= CI_ATTRIBUTES;
    }
    if (hasFinalizer(sootClass)) {
      flags |= CI_FINALIZABLE;
    }

    // Create the ClassInfoHeader structure.
    StructureConstantBuilder header = new StructureConstantBuilder();
    header.add(new NullConstant(I8_PTR)); // Points to the runtime Class struct
    header.add(new IntegerConstant(flags));
    header.add(getString(getInternalName(sootClass)));
    if (sootClass.declaresMethod("<clinit>", Collections.emptyList(), VoidType.v())) {
      SootMethod method = sootClass.getMethod("<clinit>", Collections.emptyList(), VoidType.v());
      header.add(new FunctionRef(mangleMethod(method), getFunctionType(method)));
    } else {
      header.add(new NullConstant(I8_PTR));
    }
    header.add(sizeof(classType));
    header.add(sizeof(instanceType));
    if (!instanceFields.isEmpty()) {
      header.add(offsetof(instanceType, 1, 1));
    } else {
      header.add(sizeof(instanceType));
    }
    header.add(new IntegerConstant((short) countReferences(classFields)));
    header.add(new IntegerConstant((short) countReferences(instanceFields)));

    PackedStructureConstantBuilder body = new PackedStructureConstantBuilder();
    body.add(new IntegerConstant((short) sootClass.getInterfaceCount()));
    body.add(new IntegerConstant((short) sootClass.getFieldCount()));
    body.add(new IntegerConstant((short) sootClass.getMethodCount()));

    if (!sootClass.isInterface()) {
      body.add(
          getStringOrNull(
              sootClass.hasSuperclass() ? getInternalName(sootClass.getSuperclass()) : null));
    }

    if (attributesEncoder.classHasAttributes()) {
      body.add(new ConstantBitcast(attributesEncoder.getClassAttributes().ref(), I8_PTR));
    }

    for (SootClass s : sootClass.getInterfaces()) {
      body.add(getString(getInternalName(s)));
    }

    for (SootField f : sootClass.getFields()) {
      flags = 0;
      soot.Type t = f.getType();
      if (t instanceof PrimType) {
        if (t.equals(BooleanType.v())) {
          flags |= DESC_Z;
        } else if (t.equals(ByteType.v())) {
          flags |= DESC_B;
        } else if (t.equals(ShortType.v())) {
          flags |= DESC_S;
        } else if (t.equals(CharType.v())) {
          flags |= DESC_C;
        } else if (t.equals(IntType.v())) {
          flags |= DESC_I;
        } else if (t.equals(LongType.v())) {
          flags |= DESC_J;
        } else if (t.equals(FloatType.v())) {
          flags |= DESC_F;
        } else if (t.equals(DoubleType.v())) {
          flags |= DESC_D;
        }
        flags <<= 12;
      }
      if (Modifier.isPublic(f.getModifiers())) {
        flags |= FI_PUBLIC;
      } else if (Modifier.isPrivate(f.getModifiers())) {
        flags |= FI_PRIVATE;
      } else if (Modifier.isProtected(f.getModifiers())) {
        flags |= FI_PROTECTED;
      }
      if (Modifier.isStatic(f.getModifiers())) {
        flags |= FI_STATIC;
      }
      if (Modifier.isFinal(f.getModifiers())) {
        flags |= FI_FINAL;
      }
      if (Modifier.isVolatile(f.getModifiers())) {
        flags |= FI_VOLATILE;
      }
      if (Modifier.isTransient(f.getModifiers())) {
        flags |= FI_TRANSIENT;
      }
      if ((f.getModifiers() & 0x1000) > 0) {
        flags |= FI_SYNTHETIC;
      }
      if (Modifier.isEnum(f.getModifiers())) {
        flags |= FI_ENUM;
      }
      if (attributesEncoder.fieldHasAttributes(f)) {
        flags |= FI_ATTRIBUTES;
      }
      body.add(new IntegerConstant((short) flags));
      body.add(getString(f.getName()));
      if (!(t instanceof PrimType)) {
        body.add(getString(getDescriptor(f)));
      }
      if (f.isStatic()) {
        int index = classFields.indexOf(f);
        body.add(offsetof(classType, 1, index, 1));
      } else {
        int index = instanceFields.indexOf(f);
        body.add(offsetof(instanceType, 1, 1 + index, 1));
      }
      if (attributesEncoder.fieldHasAttributes(f)) {
        body.add(new ConstantBitcast(attributesEncoder.getFieldAttributes(f).ref(), I8_PTR));
      }
    }

    for (SootMethod m : sootClass.getMethods()) {
      soot.Type t = m.getReturnType();
      flags = 0;
      if (Modifier.isPublic(m.getModifiers())) {
        flags |= MI_PUBLIC;
      } else if (Modifier.isPrivate(m.getModifiers())) {
        flags |= MI_PRIVATE;
      } else if (Modifier.isProtected(m.getModifiers())) {
        flags |= MI_PROTECTED;
      }
      if (Modifier.isStatic(m.getModifiers())) {
        flags |= MI_STATIC;
      }
      if (Modifier.isFinal(m.getModifiers())) {
        flags |= MI_FINAL;
      }
      if (Modifier.isSynchronized(m.getModifiers())) {
        flags |= MI_SYNCHRONIZED;
      }
      if ((m.getModifiers() & 0x0040) > 0) {
        flags |= MI_BRIDGE;
      }
      if ((m.getModifiers() & 0x0080) > 0) {
        flags |= MI_VARARGS;
      }
      if (Modifier.isNative(m.getModifiers())) {
        if (!isStruct(sootClass) && !isStructMember(m)) {
          flags |= MI_NATIVE;
        }
      }
      if (Modifier.isAbstract(m.getModifiers())) {
        flags |= MI_ABSTRACT;
      }
      if (Modifier.isStrictFP(m.getModifiers())) {
        flags |= MI_STRICT;
      }
      if ((m.getModifiers() & 0x1000) > 0) {
        flags |= MI_SYNTHETIC;
      }
      if (attributesEncoder.methodHasAttributes(m)) {
        flags |= MI_ATTRIBUTES;
      }
      if (isBridge(m)) {
        flags |= MI_BRO_BRIDGE;
      }
      if (isCallback(m)) {
        flags |= MI_BRO_CALLBACK;
      }
      if ((t instanceof PrimType || t == VoidType.v()) && m.getParameterCount() == 0) {
        flags |= MI_COMPACT_DESC;
      }
      body.add(new IntegerConstant((short) flags));

      body.add(getString(m.getName()));

      if ((flags & MI_COMPACT_DESC) > 0) {
        int desc = 0;
        if (t.equals(BooleanType.v())) {
          desc = DESC_Z;
        } else if (t.equals(ByteType.v())) {
          desc = DESC_B;
        } else if (t.equals(ShortType.v())) {
          desc = DESC_S;
        } else if (t.equals(CharType.v())) {
          desc = DESC_C;
        } else if (t.equals(IntType.v())) {
          desc = DESC_I;
        } else if (t.equals(LongType.v())) {
          desc = DESC_J;
        } else if (t.equals(FloatType.v())) {
          desc = DESC_F;
        } else if (t.equals(DoubleType.v())) {
          desc = DESC_D;
        } else if (t.equals(VoidType.v())) {
          desc = DESC_V;
        }
        body.add(new IntegerConstant((byte) desc));
      } else {
        body.add(getString(getDescriptor(m)));
      }
      if (attributesEncoder.methodHasAttributes(m)) {
        body.add(new ConstantBitcast(attributesEncoder.getMethodAttributes(m).ref(), I8_PTR));
      }
      if (!m.isAbstract()) {
        body.add(new ConstantBitcast(new FunctionRef(mangleMethod(m), getFunctionType(m)), I8_PTR));
        body.add(
            new IntegerConstant(
                DUMMY_METHOD_SIZE)); // Size of function. This value will be modified later by
                                     // patching the .s file.
        if (m.isSynchronized()) {
          body.add(
              new ConstantBitcast(
                  new FunctionRef(mangleMethod(m) + "_synchronized", getFunctionType(m)), I8_PTR));
        }
      }
      if (isBridge(m)) {
        body.add(new GlobalRef(BridgeMethodCompiler.getTargetFnPtrName(m), I8_PTR));
      }
      if (isCallback(m)) {
        body.add(
            new ConstantBitcast(
                new FunctionRef(mangleMethod(m) + "_callback", getCallbackFunctionType(m)),
                I8_PTR));
      }
    }

    // Return the struct {header, body}. To be compatible with the C code in classinfo.c
    // it is important that the header is padded the same as in C so that the body starts
    // after sizeof(ClassInfoHeader) bytes.
    return new StructureConstantBuilder().add(header.build()).add(body.build()).build();
  }
Beispiel #9
0
  private void compile(Clazz clazz, OutputStream out) throws IOException {
    sootClass = clazz.getSootClass();
    mb = new ModuleBuilder();
    trampolines = new HashSet<Trampoline>();
    catches = new HashSet<String>();
    classFields = getClassFields(sootClass);
    instanceFields = getInstanceFields(sootClass);
    classType = getClassType(sootClass);
    instanceType = getInstanceType(sootClass);

    attributesEncoder.encode(mb, sootClass);

    // Add a <clinit> method if the class has ConstantValueTags but no <clinit>.
    // This has to be done before createInfoStruct() is called otherwise the
    // ClassInfoHeader->initializer value will become NULL and constant static fields
    // will never be initialized.
    if (!sootClass.declaresMethodByName("<clinit>") && hasConstantValueTags(classFields)) {
      SootMethod clinit =
          new SootMethod("<clinit>", Collections.EMPTY_LIST, VoidType.v(), Modifier.STATIC);
      JimpleBody body = Jimple.v().newBody(clinit);
      clinit.setActiveBody(body);
      body.getUnits().add(new JReturnVoidStmt());
      this.sootClass.addMethod(clinit);
    }

    if (isStruct(sootClass)) {
      if (!Modifier.isFinal(sootClass.getModifiers())) {
        throw new IllegalArgumentException("Struct class must be final");
      }
      SootMethod _sizeOf =
          new SootMethod("_sizeOf", Collections.EMPTY_LIST, IntType.v(), Modifier.PROTECTED);
      sootClass.addMethod(_sizeOf);
      SootMethod sizeOf =
          new SootMethod(
              "sizeOf", Collections.EMPTY_LIST, IntType.v(), Modifier.PUBLIC | Modifier.STATIC);
      sootClass.addMethod(sizeOf);
    }

    mb.addInclude(
        getClass()
            .getClassLoader()
            .getResource(
                String.format("header-%s-%s.ll", config.getOs().getFamily(), config.getArch())));
    mb.addInclude(getClass().getClassLoader().getResource("header.ll"));

    mb.addFunction(createInstanceof());
    mb.addFunction(createCheckcast());
    mb.addFunction(createLdcClass());
    mb.addFunction(createLdcClassWrapper());
    Function allocator = createAllocator();
    mb.addFunction(allocator);
    mb.addFunction(createClassInitWrapperFunction(allocator.ref()));

    for (SootField f : sootClass.getFields()) {
      Function getter = createFieldGetter(f);
      Function setter = createFieldSetter(f);
      mb.addFunction(getter);
      mb.addFunction(setter);
      if (f.isStatic() && !f.isPrivate()) {
        mb.addFunction(createClassInitWrapperFunction(getter.ref()));
        if (!f.isFinal()) {
          mb.addFunction(createClassInitWrapperFunction(setter.ref()));
        }
      }
    }

    for (SootMethod method : sootClass.getMethods()) {
      String name = method.getName();
      if (isBridge(method)) {
        bridgeMethod(method);
      } else if (isStruct(sootClass)
          && ("_sizeOf".equals(name) || "sizeOf".equals(name) || isStructMember(method))) {
        structMember(method);
      } else if (method.isNative()) {
        nativeMethod(method);
      } else if (!method.isAbstract()) {
        method(method);
      }
      if (!name.equals("<clinit>")
          && !name.equals("<init>")
          && !method.isPrivate()
          && !method.isStatic()
          && !Modifier.isFinal(method.getModifiers())
          && !Modifier.isFinal(sootClass.getModifiers())) {

        createLookupFunction(method);
      }
      if (method.isStatic()) {
        String fnName = mangleMethod(method);
        if (method.isSynchronized()) {
          fnName += "_synchronized";
        }
        FunctionRef fn = new FunctionRef(fnName, getFunctionType(method));
        mb.addFunction(createClassInitWrapperFunction(fn));
      }
    }

    Set<String> trampolineDependencies = new HashSet<String>();
    for (Trampoline trampoline : trampolines) {
      trampolineResolver.compile(mb, trampoline);
      trampolineDependencies.addAll(trampolineResolver.getDependencies());
    }

    Global classInfoStruct = null;
    StructureConstant classInfoErrorStruct = createClassInfoErrorStruct();
    if (classInfoErrorStruct != null) {
      // The class cannot be loaded at runtime. Replace the ClassInfo struct
      // with a ClassInfoError struct with details of why.
      classInfoStruct = new Global(mangleClass(sootClass) + "_info_struct", classInfoErrorStruct);
    } else {
      classInfoStruct =
          new Global(mangleClass(sootClass) + "_info_struct", createClassInfoStruct());
    }
    mb.addGlobal(classInfoStruct);

    Function infoFn = FunctionBuilder.infoStruct(sootClass);
    infoFn.add(new Ret(new ConstantBitcast(classInfoStruct.ref(), I8_PTR_PTR)));
    mb.addFunction(infoFn);

    out.write(mb.build().toString().getBytes("UTF-8"));

    clazz.clearDependencies();
    clazz.addDependency(
        "java/lang/Object"); // Make sure no class or interface has zero dependencies
    if (sootClass.hasSuperclass() && !sootClass.isInterface()) {
      clazz.addDependency(getInternalName(sootClass.getSuperclass()));
    }
    for (SootClass iface : sootClass.getInterfaces()) {
      clazz.addDependency(getInternalName(iface));
    }
    for (SootField f : sootClass.getFields()) {
      addDependencyIfNeeded(clazz, f.getType());
    }
    for (SootMethod m : sootClass.getMethods()) {
      addDependencyIfNeeded(clazz, m.getReturnType());
      @SuppressWarnings("unchecked")
      List<soot.Type> paramTypes = (List<soot.Type>) m.getParameterTypes();
      for (soot.Type type : paramTypes) {
        addDependencyIfNeeded(clazz, type);
      }
    }
    clazz.addDependencies(attributesEncoder.getDependencies());
    clazz.addDependencies(trampolineDependencies);
    clazz.addDependencies(catches);

    for (Trampoline t : trampolines) {
      if (!(t instanceof LdcString)) {
        String desc = t.getTarget();
        if (desc.charAt(0) == 'L' || desc.charAt(0) == '[') {
          // Target is a descriptor
          addDependencyIfNeeded(clazz, desc);
        } else {
          clazz.addDependency(t.getTarget());
        }
      }
      if (t instanceof FieldAccessor) {
        addDependencyIfNeeded(clazz, ((FieldAccessor) t).getFieldDesc());
      } else if (t instanceof Invoke) {
        String methodDesc = ((Invoke) t).getMethodDesc();
        addDependencyIfNeeded(clazz, getReturnTypeDescriptor(methodDesc));
        for (String desc : getParameterDescriptors(methodDesc)) {
          addDependencyIfNeeded(clazz, desc);
        }
      }
    }
    clazz.saveDependencies();
  }
Beispiel #10
0
  public Code(TypeVars tvars) {

    this.j = Jimple.v();

    this.localX = j.newLocal("x", IntType.v());
    this.localY = j.newLocal("y", IntType.v());
    this.localZ = j.newLocal("z", IntType.v());
    this.localO = j.newLocal("o", RefType.v("java.lang.Object"));
    this.localT = j.newLocal("t", RefType.v("TestClass"));
    this.localThis = j.newLocal("this", RefType.v("TestClass"));
    this.varX = Var.fromLocal(localX);
    this.varY = Var.fromLocal(localY);
    this.varZ = Var.fromLocal(localZ);
    this.varO = Var.fromLocal(localO);
    this.varT = Var.fromLocal(localT);
    this.varThis = Var.fromLocal(localThis);
    this.tvarX = tvars.testParam(varX, "");
    this.tvarY = tvars.testParam(varY, "");
    this.tvarZ = tvars.testParam(varZ, "");
    this.tvarO = tvars.testParam(varO, "");
    this.tvarT = tvars.testParam(varT, "");
    this.tvarThis = tvars.testParam(varThis, "");

    this.init =
        Environments.makeEmpty()
            .add(varX, tvarX)
            .add(varY, tvarY)
            .add(varZ, tvarZ)
            .add(varO, tvarO)
            .add(varT, tvarT)
            .add(varThis, tvarThis);

    this.testClass = makeFreshClass("TestClass");

    Map<SootField, TypeDomain.Type<Level>> fieldMap = new HashMap<>();

    this.testLowField_int = new SootField("testLowField", IntType.v(), 0);
    testClass.addField(this.testLowField_int);
    fieldMap.put(testLowField_int, TLOW);
    this.testHighField_int = new SootField("testHighField", IntType.v(), 0);
    testClass.addField(this.testHighField_int);
    fieldMap.put(testHighField_int, THIGH);
    this.testStaticDynField_int = new SootField("testStaticDynField", IntType.v(), Modifier.STATIC);
    testClass.addField(this.testStaticDynField_int);
    fieldMap.put(testStaticDynField_int, DYN);

    // freeze field map
    this.fields = new FieldTable<>(fieldMap);

    Map<SootMethod, Signature<Level>> sigMap = new HashMap<>();
    Symbol.Param<LowHigh.Level> param_x = param(0);
    Symbol.Param<LowHigh.Level> param_y = param(1);

    // Method:
    // int testCallee()
    //    with {} effect {}
    this.testCallee__int =
        new SootMethod("testCallee", Collections.emptyList(), IntType.v(), Modifier.ABSTRACT);
    this.testClass.addMethod(testCallee__int);
    sigMap.put(
        this.testCallee__int,
        makeSignature(
            this.testCallee__int.getParameterCount(),
            Stream.of(leS(Symbol.literal(PUB), ret())).collect(toList()),
            Effects.emptyEffect()));

    // Method:
    // int testCallee_int_int__int (int, int)
    //   with {@param1 <= @ret, @param2 <= @ret} effect {}
    this.testCallee_int_int__int =
        new SootMethod(
            "testCallee", asList(IntType.v(), IntType.v()), IntType.v(), Modifier.ABSTRACT);
    this.testClass.addMethod(testCallee_int_int__int);
    Stream<SigConstraint<Level>> sigCstrs = Stream.of(leS(param_x, ret()), leS(param_y, ret()));
    sigMap.put(
        this.testCallee_int_int__int,
        makeSignature(
            this.testCallee_int_int__int.getParameterCount(),
            sigCstrs.collect(toList()),
            Effects.emptyEffect()));

    // Method:
    // int ignoreSnd(int, int)
    //   with { @param1 <= @ret } effect {}
    this.ignoreSnd_int_int__int =
        new SootMethod(
            "ignoreSnd", asList(IntType.v(), IntType.v()), IntType.v(), Modifier.ABSTRACT);
    this.testClass.addMethod(ignoreSnd_int_int__int);
    sigCstrs = Stream.of(leS(param_x, ret()), leS(param_y, param_y));
    sigMap.put(
        this.ignoreSnd_int_int__int,
        makeSignature(
            this.ignoreSnd_int_int__int.getParameterCount(),
            sigCstrs.collect(toList()),
            Effects.emptyEffect()));

    // Method:
    // int writeToLowReturn0(int)
    //   with { @param0 <= LOW } effect { LOW }
    this.writeToLowReturn0_int__int =
        new SootMethod("writeToLow", singletonList(IntType.v()), IntType.v(), Modifier.ABSTRACT);
    this.testClass.addMethod(this.writeToLowReturn0_int__int);
    sigCstrs = Stream.of((leS(param_x, literal(TLOW))), leS(ret(), ret()));
    sigMap.put(
        this.writeToLowReturn0_int__int,
        makeSignature(
            this.writeToLowReturn0_int__int.getParameterCount(),
            sigCstrs.collect(toList()),
            Effects.makeEffects(TLOW)));

    // Method:
    // int ignore0Low1ReturnHigh(int, int)
    //   with { @param1 <= LOW, HIGH <= ret } effect {}
    this.ignore0Low1ReturnHigh =
        new SootMethod(
            "ignore0Low1ReturnHigh",
            asList(IntType.v(), IntType.v()),
            IntType.v(),
            Modifier.ABSTRACT);
    this.testClass.addMethod(this.ignore0Low1ReturnHigh);
    sigCstrs = Stream.of(leS(param(1), literal(TLOW)), leS(literal(THIGH), ret()));
    sigMap.put(
        this.ignore0Low1ReturnHigh,
        makeSignature(
            this.ignore0Low1ReturnHigh.getParameterCount(),
            sigCstrs.collect(toList()),
            Effects.emptyEffect()));

    // freeze signatures
    this.signatures = makeTable(sigMap);
  }
  /**
   * Generate Policy Enforcement Point (PEP) for Unit 'unit'.
   *
   * @param unit
   * @param invExpr
   * @param body
   * @param dataFlowAvailable
   * @param assignmentStatement
   * @return
   */
  private List<Unit> generatePolicyEnforcementPoint(
      Unit unit,
      InvokeExpr invExpr,
      Body body,
      int dataFlowAvailable,
      boolean assignmentStatement) {

    log.debug("Dataflow available: " + dataFlowAvailable);

    List<Unit> generated = new ArrayList<Unit>(); // store all new units that are generated

    String methodSignature = invExpr.getMethod().getSignature();
    EventInformation eventInfo = allEventInformation.get(methodSignature);
    String eventName = eventInfo.getEventName();

    Set<Pair<Integer, String>> allParameterInformation = eventInfo.getParameterInformation();

    // This list containts types and parameters that are used to build the
    // invoke expression to "isStmtExecutionAllowed':
    //
    // java.lang.String   "eventName"
    // IntType            "dataFlowAvailable"
    // java.lang.Object[] "parameters"
    //
    List<Object> parameterForHelperMethod = new ArrayList<Object>();
    List<Object> categories = new ArrayList<Object>();

    // add event name information
    Type eventNameType = RefType.v("java.lang.String");
    parameterForHelperMethod.add(eventNameType);
    StringConstant eventNameConstant = StringConstant.v(eventName);
    parameterForHelperMethod.add(eventNameConstant);

    // add information about dataflow availability
    parameterForHelperMethod.add(IntType.v());
    parameterForHelperMethod.add(IntConstant.v(dataFlowAvailable));

    // add information about parameters
    parameterForHelperMethod.add(getParameterArrayType());
    List<Value> paramValues = new ArrayList<Value>();

    for (Pair<Integer, String> parameterInfo : allParameterInformation) {
      paramValues.add(StringConstant.v("param" + parameterInfo.getLeft() + "value"));
      paramValues.add(invExpr.getArg(parameterInfo.getLeft()));
    }

    Pair<Value, List<Unit>> arrayRefAndInstrumentation = generateParameterArray(paramValues, body);

    generated.addAll(arrayRefAndInstrumentation.getRight());

    parameterForHelperMethod.add(arrayRefAndInstrumentation.getLeft());

    // Generate PEP call to the PDP. Store the result send by the PDP to 'resultPDPLocal'
    // Pseudo code looks like this:
    //
    // resultPDPLocal = isStmtExecutionAllowed(eventName, dataFlowAvailable, parameters);
    //
    StaticInvokeExpr sie =
        Instrumentation.createJimpleStaticInvokeExpr(
            Settings.INSTRUMENTATION_HELPER_JAVA,
            "isStmtExecutionAllowed",
            parameterForHelperMethod);

    Local resultPDPLocal = generateFreshLocal(body, soot.IntType.v());
    AssignStmt asssCondition = Jimple.v().newAssignStmt(resultPDPLocal, sie);
    generated.add(asssCondition);

    for (Unit u : generated) {
      System.out.println("isStmt gen: " + u);
    }

    if (assignmentStatement) {
      // If the method call before which the PEP in inserted is an assignment statement of
      // the form "resultPDPLocal = originalCallThatIsChecked()", generate a new assignment
      // statement that stores a default value to "resultPDPLocal" if the PDP does not
      // allow the call of method originalCallThatIsChecked().
      //
      // Pseudo-code:
      //
      // if(resultPDPLocal == 0) goto dummyLabel:
      // result = originalCallThatIsChecked();
      // goto dummyLabel2:
      // dummyLabel:
      // result = dummyValue (i.e., 0 for IntType, false for BooleanType, ...)
      // dummyLabel2:
      // nop
      //

      if (unit instanceof DefinitionStmt) {
        DefinitionStmt defStmt = (DefinitionStmt) unit;

        Value pepCondition = Jimple.v().newEqExpr(resultPDPLocal, IntConstant.v(0));

        // insert nop
        Unit label2Nop = Jimple.v().newNopStmt();
        body.getUnits().insertAfter(label2Nop, unit);

        // insert result = dummyValue
        Unit dummyStatement = createCorrectDummyAssignment((Local) defStmt.getLeftOp());
        body.getUnits().insertAfter(dummyStatement, unit);
        log.debug("insert c: " + dummyStatement);

        // insert goto dummyLabel2:
        body.getUnits().insertAfter(Jimple.v().newGotoStmt(label2Nop), unit);

        IfStmt ifStmt = Jimple.v().newIfStmt(pepCondition, dummyStatement);
        generated.add(ifStmt);
      } else {
        throw new RuntimeException(
            "error: expected DefinitionStmt got " + unit + " -> " + unit.getClass());
      }

    } else {
      // If the method call before which the PEP in inserted is a call statement of
      // the form "originalCallThatIsChecked()", generate a new nop statement
      // to jump to if the PDP does not allow the call of method originalCallThatIsChecked().
      //
      // Pseudo-code:
      //
      // if(resultPDPLocal == 0) goto nopLabel:
      // result = originalCallThatIsChecked();
      // nopLabel:
      // nop
      //
      Value pepCondition = Jimple.v().newEqExpr(resultPDPLocal, IntConstant.v(0));

      NopStmt nopStmt = Jimple.v().newNopStmt();
      body.getUnits().insertAfter(nopStmt, unit);
      log.debug("insert d: " + nopStmt);

      IfStmt ifStmt = Jimple.v().newIfStmt(pepCondition, nopStmt);

      generated.add(ifStmt);
    }

    return generated;
  }
  /**
   * @param cfg
   * @param sink
   * @param assignmentStatement
   */
  private void instrumentSourceToSinkConnections(
      BiDiInterproceduralCFG<Unit, SootMethod> cfg,
      ResultSinkInfo sink,
      boolean assignmentStatement) {
    sourceSinkConnectionCounter += 1;

    // loop through the sinks
    for (ResultSinkInfo key : results.getResults().keySet()) {

      log.debug("compare: " + key);
      log.debug("     to: " + sink);

      // if the current sink is the sink at the unit tagged with 'sink'
      if (key.equals(sink)) {

        // loop through the sources
        for (ResultSourceInfo si : results.getResults().get(key)) {

          Stmt stmt = si.getSource();
          SootMethod sm = cfg.getMethodOf(stmt);
          Body body = sm.retrieveActiveBody();

          // Source instrumentation. The three type categories for the source are:
          // - callback
          // - ICC source method (i.e., Intent.getExtras())
          // - not a callback and not an ICC source method (i.e., getLine1Number())
          //
          if (isInterComponentSourceCallback(si, cfg)) {
            throw new RuntimeException("Callbacks as sources are not supported right now");
          } else if (isInterComponentSourceNoCallback(si, cfg)) {
            // only invoke expression are treated here
            if (stmt.containsInvokeExpr()) {
              // only statements that return a android.os.Bundle are currently supported
              if (stmt instanceof DefinitionStmt) {
                DefinitionStmt defStmt = (DefinitionStmt) stmt;
                Value leftValue = defStmt.getLeftOp();

                if (leftValue.getType().equals(RefType.v("android.os.Bundle"))) {
                  List<Object> args = new ArrayList<Object>();
                  args.add(IntType.v());
                  args.add(IntConstant.v(sourceSinkConnectionCounter));
                  args.add(RefType.v("android.os.Bundle"));
                  args.add(leftValue);
                  InvokeExpr invExpr =
                      Instrumentation.createJimpleStaticInvokeExpr(
                          Settings.INSTRUMENTATION_HELPER_JAVA,
                          "registerNewSourceSinkConnection",
                          args);
                  InvokeStmt invStmt = Jimple.v().newInvokeStmt(invExpr);

                  Unit instrumentationPoint = null;
                  if (stmt instanceof IdentityStmt) {
                    instrumentationPoint = getLastIdentityStmt(body);
                  } else {
                    instrumentationPoint = stmt;
                  }
                  body.getUnits().insertAfter(invStmt, instrumentationPoint);
                  log.debug("insert a: " + invStmt);
                } else {
                  System.err.println("We do only support android.os.Bundle right now!");
                }
              }
            }
          } else {

            String sourceCat = getSourceCategory(si);
            if (sourceCat != null) {
              List<Object> args = new ArrayList<Object>();
              args.add(IntType.v());
              args.add(IntConstant.v(sourceSinkConnectionCounter));
              args.add(RefType.v("java.lang.String"));
              args.add(StringConstant.v(sourceCat));
              InvokeExpr invExpr =
                  Instrumentation.createJimpleStaticInvokeExpr(
                      Settings.INSTRUMENTATION_HELPER_JAVA,
                      "registerNewSourceSinkConnection",
                      args);
              InvokeStmt invStmt = Jimple.v().newInvokeStmt(invExpr);

              Unit instrumentationPoint = null;
              if (stmt instanceof IdentityStmt) instrumentationPoint = getLastIdentityStmt(body);
              else instrumentationPoint = stmt;
              body.getUnits().insertAfter(invStmt, instrumentationPoint);
              log.debug("insert b: " + invStmt);
            }
          }

          // sink instrumentation
          if (sink.getSink().containsInvokeExpr()) {
            Body bodyOfSink = cfg.getMethodOf(key.getSink()).getActiveBody();
            InvokeExpr invExpr = sink.getSink().getInvokeExpr();
            List<Unit> generated = new ArrayList<Unit>();
            generated.addAll(
                instrumentIntentAddings(cfg, stmt, invExpr, results.getResults().get(key)));

            EventInformation sinkEventInfo =
                allEventInformation.get(invExpr.getMethod().getSignature());
            EventInformation sourceEventInfo =
                allEventInformation.get(si.getSource().getInvokeExpr().getMethod().getSignature());

            generated.addAll(
                generatePolicyEnforcementPoint(
                    key.getSink(),
                    invExpr,
                    bodyOfSink,
                    sourceSinkConnectionCounter,
                    assignmentStatement));

            log.debug("body with data flow:\n" + body);
            for (Unit u : generated) {
              log.debug("gen: " + u);
            }

            if (sinkEventInfo.isInstrumentAfterStatement())
              bodyOfSink.getUnits().insertAfter(generated, key.getSink());
            else bodyOfSink.getUnits().insertBefore(generated, key.getSink());
          } else throw new RuntimeException("Double-Check the assumption");
        } // loop through the sources
      } // if the sink at the unit is the current sink
    } // loop through the sinks
  }
Beispiel #13
0
 public Type getType() {
   return IntType.v();
 }