/**
   * For a concrete method (declared in an application class), find statements containing an invoke
   * expression for which the method is one of the method in 'allEventInformation' (i.e.,
   * getLine1Number(), ...).
   *
   * @param cfg
   */
  private void doAccessControlChecks(BiDiInterproceduralCFG<Unit, SootMethod> cfg) {
    for (SootClass sc : Scene.v().getApplicationClasses()) {
      for (SootMethod sm : sc.getMethods()) {
        if (sm.isConcrete()) {
          Body body = sm.retrieveActiveBody();
          // only instrument application methods (i.e., not methods declared in PEP helper classes
          // or in a Java library classes or in an Android classes, ...)
          if (isInstrumentationNecessary(sm)) {

            // important to use snapshotIterator here
            Iterator<Unit> i = body.getUnits().snapshotIterator();
            log.debug("method: " + sm);
            while (i.hasNext()) {
              Stmt s = (Stmt) i.next();

              if (s.containsInvokeExpr()) {
                InvokeExpr invExpr = s.getInvokeExpr();
                String methodSignature = invExpr.getMethod().getSignature();

                if (allEventInformation.containsKey(methodSignature)) {
                  log.debug("statement " + s + " matches " + methodSignature + ".");
                  ResultSinkInfo sink = null;

                  outer:
                  for (ResultSinkInfo key : results.getResults().keySet()) {

                    // iterate over all the arguments of the invoke expression
                    // and check if an argument is a tainted sink. If one is
                    // set variable 'sink' to the ResultSinkInfo key.
                    for (Value v : invExpr.getArgs()) {
                      Value pathValue = key.getAccessPath().getPlainValue();
                      if (v == pathValue) {
                        sink = key;
                        log.debug("found a sink: " + pathValue);
                        break outer;
                      }
                    }
                  }

                  if (sink != null) {
                    log.debug("instrument with data flow information )" + s + ")");
                    instrumentSourceToSinkConnections(cfg, sink, s instanceof AssignStmt);
                    instrumentWithNoDataFlowInformation(
                        methodSignature, s, invExpr, body, s instanceof AssignStmt);
                  } else {
                    log.debug("instrument without data flow information (" + s + ")");
                    instrumentWithNoDataFlowInformation(
                        methodSignature, s, invExpr, body, s instanceof AssignStmt);
                  }
                }
              } // if stmt containts invoke expression
            } // loop on statements
          }
        }
      }
    }
  }
  /**
   * Make sure that all invoke special targets are cloned into the class from ancestors. This might
   * mean that we have to clone hidden methods, and change their names. So clone them in, and update
   * the clone to original map, and update the invoke special Also, this will update invoke specials
   * that target methods cloned in previous call to above cloneReachableNonHiddenAncestorMethods()
   */
  private void cloneHiddenAncestorMethodsAndFixInvokeSpecial() {
    Set<SootClass> parents = SootUtils.getParents(clazz);

    boolean debug = false; // (clazz.getName().contains("ResultDisplayer"));

    boolean cloneAdded = false;
    do {
      cloneAdded = false;
      for (SootMethod method : clazz.getMethods()) {

        if (method.isAbstract() || method.isPhantom() || !method.isConcrete()) continue;

        if (debug) System.out.println(method);

        Body body = null;
        try {
          body = method.retrieveActiveBody();
        } catch (Exception ex) {
          logger.info("Exception retrieving method body {}", ex);
          continue;
        }

        StmtBody stmtBody = (StmtBody) body;

        Chain units = stmtBody.getUnits();
        Iterator stmtIt = units.iterator();

        while (stmtIt.hasNext()) {
          Stmt stmt = (Stmt) stmtIt.next();

          if (stmt.containsInvokeExpr() && stmt.getInvokeExpr() instanceof SpecialInvokeExpr) {
            SpecialInvokeExpr si = (SpecialInvokeExpr) stmt.getInvokeExpr();

            SootMethod target = resolveSpecialInvokeTarget(si); // si.getMethod();

            if (debug) System.out.printf("\t%s %s", si, target);

            if (clonedToOriginal.values().contains(target)) {
              // found target of invoke special, and it has been cloned, so change the invoke
              // special
              SootMethod cloneOfTarget = clonedToOriginal.inverse().get(target);
              si.setMethodRef(cloneOfTarget.makeRef());
              if (debug) System.out.println("\tChange ref " + cloneOfTarget);
            } else if (parents.contains(target.getDeclaringClass())) {
              // target has not been cloned, but should be cloned, so clone it and change ref of
              // invoke
              String name = target.getName() + CLONED_METHOD_SUFFIX + (cloned_method_id++);
              SootMethod clonedMethod = cloneMethod(target, name);
              si.setMethodRef(clonedMethod.makeRef());
              cloneAdded = true;
              if (debug) System.out.println("\tClone and Change ref " + clonedMethod);
            }
          }
        }
      }
    } while (cloneAdded);
  }
Beispiel #3
0
    @Override
    public String toString() {
      StringBuilder sb = new StringBuilder(context.toString());

      if (context.hasTag("LineNumberTag"))
        sb.append(" on line ")
            .append(((LineNumberTag) context.getTag("LineNumberTag")).getLineNumber());

      return sb.toString();
    }
  public static boolean isTarget(
      AnalysisDirection direction,
      SootMethod enclosingMethod,
      Unit unit,
      Iterable<AnalysisTarget> targets) {
    if (!(unit instanceof AssignStmt)) return false;

    Stmt s = (Stmt) unit;
    if (!s.containsInvokeExpr()) return false;

    InvokeExpr ie = s.getInvokeExpr();
    for (AnalysisTarget target : targets) {
      if (target.matches(direction, enclosingMethod, ie)) return true;
    }
    return false;
  }
  private void dumpTextGraph(SootMethod caller, PrintStream printStream, int level) {

    String indent = indentString(level);
    caller.getTags();
    printStream.printf("%s %s\n", indent, caller.toString());
    Iterator<Edge> iterator = callGraph.edgesOutOf(caller);
    callgraphSet.add(caller);

    // boolean appClass = caller.getDeclaringClass().isApplicationClass();
    boolean systemApi = API.v().isSystemMethod(caller);

    /*
      printStream.printf("%s Declaring method %s: app %s\n", indent,
      caller.toString(), systemApi? "False": "True");
    */

    String subindent = indentString(level + 1);
    Set<Object> calleeSet = new HashSet<Object>();

    while (iterator != null && iterator.hasNext()) {
      Edge edge = iterator.next();
      if (!systemApi) {
        List<Stmt> invokeStmtList = SootUtils.getInvokeStatements(caller, edge.tgt());
        for (Stmt stmt : invokeStmtList) {
          if (calleeSet.contains(stmt)) continue;
          printStream.printf("%s #[%s] ", subindent, stmt);
          SourceLocationTag tag = SootUtils.getSourceLocation(stmt);
          if (tag != null) {
            printStream.printf(": %s", tag.toString());
          }
          printStream.printf("\n");
          calleeSet.add(stmt.toString());
        }
      }

      if (!callgraphSet.contains(edge.tgt())) {
        dumpTextGraph(edge.tgt(), printStream, level + 1);
      } else {
        // already in the call graph, just print it out
        if (calleeSet.contains(edge.tgt())) continue;
        printStream.printf("%s %s\n", subindent, edge.tgt().toString());
        calleeSet.add(edge.tgt());
      }
    }
  }
  /** Dumps out the call chain in json format * */
  public void dump_json(PrintStream fp, String indent) {
    fp.printf("%s{ %s,\n", indent, json_field("type", type));
    fp.printf("%s  %s,\n", indent, json_field("link", link));
    String sig = method.getSignature();
    fp.printf("%s  %s,\n", indent, json_field("signature", sig));
    if (stmt != null) {
      SootMethodRef invoke = stmt.getInvokeExpr().getMethodRef();
      String invokeSig;
      try {
        SootMethod concrete = SootUtils.resolve(stmt.getInvokeExpr().getMethodRef());
        invokeSig = concrete.getSignature();
      } catch (CannotFindMethodException e1) {
        logger.debug("Cannot find concrete method for {} in SourceCallChainInfo.dump_json()", stmt);
        invokeSig = invoke.getSignature();
      }
      if (!invokeSig.equals(sig)) {
        fp.printf("%s  %s,\n", indent, json_field("source-signature", invokeSig));
      }
    }
    SourceLocationTag slt =
        (stmt == null) ? SootUtils.getMethodLocation(method) : getSourceLocation(stmt);
    if (slt != null) {
      fp.printf("%s  %s", indent, json_field("src-loc"));
      fp.printf(
          "{ %s, %s},\n", json_field("class", slt.getClz()), json_field("line", slt.getLine()));
    }
    fp.printf("%s  %s,\n", indent, json_field("syscalls", syscalls));
    fp.printf("%s  %s,\n", indent, json_field("calls", calls));

    if ((contents != null) && (contents.length > 0)) {
      fp.printf("%s  %s,\n", indent, json_field("score", score));
      fp.printf("%s  %s [\n", indent, json_field("contents"));
      String delim = "";
      for (SourceCallChainInfo cci : contents) {
        fp.print(delim);
        delim = ",\n";
        cci.dump_json(fp, indent + "  ");
      }
      fp.printf("\n%s]}", indent);
    } else {
      fp.printf("%s  %s\n", indent, json_field("score", score));
      fp.printf("%s}", indent);
    }
  }
Beispiel #7
0
 public static boolean isDifferentStartEndPos(Stmt s) {
   List<Tag> tags = s.getTags();
   for (Tag tag : tags) {
     if (tag instanceof SourceLnNamePosTag) {
       SourceLnNamePosTag lineTag = (SourceLnNamePosTag) tag;
       if (lineTag.startLn() != lineTag.endLn()) return true;
       else return false;
     }
   }
   return false;
 }
  @SuppressWarnings({"unchecked", "rawtypes"})
  private Set<SootField> collectBlockField(JavaCriticalSection cs) {
    Set result = new HashSet();
    int startLine = cs.getStartLine();
    int endLine = cs.getEndline();
    Body body = cs.getSootMethod().getActiveBody();
    PatchingChain<Unit> units = body.getUnits();
    for (Unit u : units) {
      Stmt s = (Stmt) u;
      LineNumberTag linetag = (LineNumberTag) s.getTag("LineNumberTag");
      if (linetag == null) continue;
      int line = linetag.getLineNumber();
      if (line < startLine || line > endLine) {
        continue;
      }

      List<ValueBox> Fieldslist = u.getUseBoxes();
      Fieldslist.addAll(u.getDefBoxes());
      for (ValueBox box : Fieldslist) {
        Value v = box.getValue();
        if (v instanceof JInstanceFieldRef) {
          result.add(((JInstanceFieldRef) v).getField());
        }
      }
      if (s.containsInvokeExpr()) {
        // 用调用图获得调用目标
        Callees callees = new Callees(getCallGragh(), u);
        for (SootMethod invokeMethod : callees.explicits()) {
          if (invokeMethod == null) continue;
          Collection use = scaner.getUseInstanceFields(invokeMethod);
          Collection mod = new HashSet();
          if (needMod) {
            mod.addAll(scaner.getModInstanceFields(invokeMethod));
          }
          if (use != null) result.addAll(use);
          result.addAll(mod);
        }
      }
    }
    return result;
  }
  @Override
  public Type appliesInternal(AndroidMethod method) {
    SootMethod sm = getSootMethod(method);

    if (sm == null) {
      System.err.println("Method not declared: " + method);
      return Type.NOT_SUPPORTED;
    }

    // We are only interested in setters
    if (!sm.isConcrete()) return Type.NOT_SUPPORTED;

    try {
      Set<Value> paramVals = new HashSet<Value>();
      for (Unit u : sm.retrieveActiveBody().getUnits()) {
        // Collect the parameters
        if (u instanceof IdentityStmt) {
          IdentityStmt id = (IdentityStmt) u;
          if (id.getRightOp() instanceof ParameterRef) paramVals.add(id.getLeftOp());
        }

        // Check for invocations
        if (u instanceof Stmt) {
          Stmt stmt = (Stmt) u;
          if (stmt.containsInvokeExpr())
            if (stmt.getInvokeExpr() instanceof InstanceInvokeExpr) {
              InstanceInvokeExpr iinv = (InstanceInvokeExpr) stmt.getInvokeExpr();
              if (paramVals.contains(iinv.getBase()))
                if (iinv.getMethod().getName().startsWith(methodName)) return Type.TRUE;
            }
        }
      }
      return Type.FALSE;
    } catch (Exception ex) {
      System.err.println("Something went wrong:");
      ex.printStackTrace();
      return Type.NOT_SUPPORTED;
    }
  }
Beispiel #10
0
 /** @apilevel low-level */
 public void flushCache() {
   super.flushCache();
   isDAafter_Variable_values = null;
   isDUafter_Variable_values = null;
   canCompleteNormally_computed = false;
   typeNullPointerException_computed = false;
   typeNullPointerException_value = null;
   handlesException_TypeDecl_values = null;
   typeThrowable_computed = false;
   typeThrowable_value = null;
   typeNull_computed = false;
   typeNull_value = null;
 }
Beispiel #11
0
  /**
   * Returns basic block that contains the statement, or null. If id stmt, it looks in tag of first
   * non-id stmt.
   */
  public static Block getBB(Stmt s) {
    Block bb;
    // 2010-02-26: return null when s == null
    if (s != null) {
      // move to first non-id stmt
      Stmt sNonId = s;
      if (sNonId instanceof IdentityStmt) {
        PatchingChain pchain =
            ProgramFlowGraph.inst().getContainingMethod(sNonId).retrieveActiveBody().getUnits();
        do {
          sNonId = (Stmt) pchain.getSuccOf(sNonId);
        } while (sNonId instanceof IdentityStmt);
      }

      // retrieve basic block for non-id stmt
      StmtTag sTag = (StmtTag) sNonId.getTag(StmtTag.TAG_NAME);
      bb = sTag.getBasicBlock();
    } else {
      bb = null;
    }

    return bb;
  }
Beispiel #12
0
 public static int getStatementLineNumber(Stmt s) {
   List<Tag> tags = s.getTags();
   int line = -1;
   for (Tag tag : tags) {
     if (tag instanceof SourceLnNamePosTag) {
       SourceLnNamePosTag lineTag = (SourceLnNamePosTag) tag;
       line = lineTag.startLn();
     } else if (tag instanceof LineNumberTag) {
       LineNumberTag lineTag = (LineNumberTag) tag;
       line = lineTag.getLineNumber();
     }
   }
   return line;
 }
 /**
  * Given the merge of the <code>out</code> sets, compute the <code>in</code> set for <code>d
  * </code>.
  *
  * <p>Processes the analysis for the given {@link Unit}, i.e. checks the end of an implicit flow
  * for the given unit and after that tries to apply a {@link SecurityLevelStmtSwitch} switch to
  * the statement, i.e. calculates or updates the <em>security levels</em> of the statement
  * components to check for security violations.
  *
  * @param in Current incoming map of the local variables for the given unit.
  * @param d The current unit which should be checked for security violations.
  * @param out Current outgoing map of the local variables for the given unit.
  * @see soot.toolkits.scalar.FlowAnalysis#flowThrough(java.lang.Object, java.lang.Object,
  *     java.lang.Object)
  * @see SecurityLevelStmtSwitch
  */
 @Override
 protected void flowThrough(LocalsMap in, Unit d, LocalsMap out) {
   copy(in, out);
   Stmt stmt = (Stmt) d;
   getAnalyzedEnvironment().setStmt(stmt);
   checkEndOfImplicitFlow(stmt, in, out);
   try {
     SecurityLevelStmtSwitch stmtSwitch =
         new SecurityLevelStmtSwitch(getAnalyzedEnvironment(), getStore(), in, out);
     stmt.apply(stmtSwitch);
   } catch (ProgramCounterException
       | EnvironmentNotFoundException
       | SwitchException
       | MethodParameterNotFoundException
       | LevelNotFoundException e) {
     throw new AnalysisException(
         getMsg(
             "exception.analysis.other.error_switch",
             stmt.toString(),
             getSignatureOfMethod(getAnalyzedEnvironment().getSootMethod()),
             getAnalyzedEnvironment().getSrcLn()),
         e);
   }
 }
Beispiel #14
0
  private int numMatchArgs(int numFormals, UnchangedParamsAnalysis mrpa, Stmt s) {
    FlowSet before = (FlowSet) mrpa.getFlowBefore(s);

    List args = ((InvokeExpr) s.getInvokeExpr()).getArgs();
    int matchArg = 0;
    for (int i = 0; i < numFormals; i++) {
      Value arg = (Value) args.get(i);
      for (Iterator rppIt = before.iterator(); rppIt.hasNext(); ) {
        IDValuePair rpp = (IDValuePair) rppIt.next();
        if (rpp.groupID == i && arg.equivTo(rpp.value)) {
          matchArg++;
          break;
        }
      }
    }
    return matchArg;
  }
  public static List<Value> getAllImmediateValue(Stmt stmt) {
    List<Value> rtVal = new ArrayList<Value>();

    List<ValueBox> vbs = stmt.getUseAndDefBoxes();
    Set<String> frs = new HashSet<String>();

    for (ValueBox vb : vbs) {
      Value v = vb.getValue();

      if (v instanceof FieldRef) {
        int endPos = v.toString().indexOf('.');
        String name = v.toString().substring(0, endPos);
        frs.add(name);

        Value existV = null;
        for (ValueBox vBox : vbs) {
          if (name.equals(vBox.getValue().toString())) {
            existV = vBox.getValue();
            break;
          }
        }

        if (null != existV) {
          rtVal.remove(existV);
        }

        rtVal.add(v);
      }

      if (v instanceof Immediate) {
        if (!frs.contains(v.toString())) {
          rtVal.add(v);
        }
      }
    }

    return rtVal;
  }
Beispiel #16
0
  public void internalTransform(String phaseName, Map opts) {

    Iterator it = Scene.v().getApplicationClasses().iterator();
    while (it.hasNext()) {
      SootClass sc = (SootClass) it.next();
      // make map of first line to each method
      HashMap<Integer, SootMethod> lineToMeth = new HashMap<Integer, SootMethod>();
      Iterator methIt = sc.getMethods().iterator();
      while (methIt.hasNext()) {
        SootMethod meth = (SootMethod) methIt.next();
        if (!meth.isConcrete()) continue;
        Body body = meth.retrieveActiveBody();
        Stmt s = (Stmt) body.getUnits().getFirst();
        while (s instanceof IdentityStmt) {
          s = (Stmt) body.getUnits().getSuccOf(s);
        }
        if (s.hasTag("LineNumberTag")) {
          LineNumberTag tag = (LineNumberTag) s.getTag("LineNumberTag");
          lineToMeth.put(new Integer(tag.getLineNumber()), meth);
        }
      }
      Iterator methIt2 = sc.getMethods().iterator();
      while (methIt2.hasNext()) {
        SootMethod meth = (SootMethod) methIt2.next();
        if (!meth.isConcrete()) continue;
        Body body = meth.retrieveActiveBody();
        Stmt s = (Stmt) body.getUnits().getFirst();
        while (s instanceof IdentityStmt) {
          s = (Stmt) body.getUnits().getSuccOf(s);
        }
        if (s.hasTag("LineNumberTag")) {
          LineNumberTag tag = (LineNumberTag) s.getTag("LineNumberTag");
          int line_num = tag.getLineNumber() - 1;
          // already taken
          if (lineToMeth.containsKey(new Integer(line_num))) {
            meth.addTag(new LineNumberTag(line_num + 1));
          }
          // still available - so use it for this meth
          else {
            meth.addTag(new LineNumberTag(line_num));
          }
        }
      }
    }
  }
Beispiel #17
0
 /**
  * @ast method
  * @aspect AnonymousClasses
  * @declaredat
  *     /Users/eric/Documents/workspaces/clara-soot/JastAddJ/Java1.4Frontend/AnonymousClasses.jrag:207
  */
 protected void collectExceptions(Collection c, ASTNode target) {
   super.collectExceptions(c, target);
   TypeDecl exceptionType = getExpr().type();
   if (exceptionType == typeNull()) exceptionType = typeNullPointerException();
   c.add(exceptionType);
 }
  /**
   * @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
  }
  /**
   * This method pushes all newExpr down to be the stmt directly before every invoke of the init
   * only if they are in the types list
   */
  public void internalTransform(Body b, String phaseName, Map options) {
    JimpleBody body = (JimpleBody) b;

    if (Options.v().verbose())
      G.v().out.println("[" + body.getMethod().getName() + "] Folding Jimple constructors...");

    Chain units = body.getUnits();
    List<Unit> stmtList = new ArrayList<Unit>();
    stmtList.addAll(units);

    Iterator<Unit> it = stmtList.iterator();
    Iterator<Unit> nextStmtIt = stmtList.iterator();
    // start ahead one
    nextStmtIt.next();

    SmartLocalDefs localDefs = SmartLocalDefsPool.v().getSmartLocalDefsFor(body);
    UnitGraph graph = localDefs.getGraph();
    LocalUses localUses = new SimpleLocalUses(graph, localDefs);

    /* fold in NewExpr's with specialinvoke's */
    while (it.hasNext()) {
      Stmt s = (Stmt) it.next();

      if (!(s instanceof AssignStmt)) continue;

      /* this should be generalized to ArrayRefs */
      // only deal with stmts that are an local = newExpr
      Value lhs = ((AssignStmt) s).getLeftOp();
      if (!(lhs instanceof Local)) continue;

      Value rhs = ((AssignStmt) s).getRightOp();
      if (!(rhs instanceof NewExpr)) continue;

      // check if very next statement is invoke -->
      // this indicates there is no control flow between
      // new and invoke and should do nothing
      if (nextStmtIt.hasNext()) {
        Stmt next = (Stmt) nextStmtIt.next();
        if (next instanceof InvokeStmt) {
          InvokeStmt invoke = (InvokeStmt) next;

          if (invoke.getInvokeExpr() instanceof SpecialInvokeExpr) {
            SpecialInvokeExpr invokeExpr = (SpecialInvokeExpr) invoke.getInvokeExpr();
            if (invokeExpr.getBase() == lhs) {
              break;
            }
          }
        }
      }

      // check if new is in the types list - only process these
      if (!types.contains(((NewExpr) rhs).getType())) continue;

      List lu = localUses.getUsesOf(s);
      Iterator luIter = lu.iterator();
      boolean MadeNewInvokeExpr = false;

      while (luIter.hasNext()) {
        Unit use = ((UnitValueBoxPair) (luIter.next())).unit;
        if (!(use instanceof InvokeStmt)) continue;
        InvokeStmt is = (InvokeStmt) use;
        if (!(is.getInvokeExpr() instanceof SpecialInvokeExpr)
            || lhs != ((SpecialInvokeExpr) is.getInvokeExpr()).getBase()) continue;

        // make a new one here
        AssignStmt constructStmt =
            Jimple.v()
                .newAssignStmt(((DefinitionStmt) s).getLeftOp(), ((DefinitionStmt) s).getRightOp());
        constructStmt.setRightOp(Jimple.v().newNewExpr(((NewExpr) rhs).getBaseType()));
        MadeNewInvokeExpr = true;

        // redirect jumps
        use.redirectJumpsToThisTo(constructStmt);
        // insert new one here
        units.insertBefore(constructStmt, use);

        constructStmt.addTag(s.getTag("SourceLnPosTag"));
      }
      if (MadeNewInvokeExpr) {
        units.remove(s);
      }
    }
  }
Beispiel #20
0
 public static boolean isCtorCall(Stmt s) {
   return s.containsInvokeExpr()
       && (s.getInvokeExpr() instanceof SpecialInvokeExpr)
       && s.getInvokeExpr().getMethod().getName().equals("<init>");
 }
Beispiel #21
0
  /**
   * @param g
   * @param numFormals number of parameters need to be taken into account, since abc will generate
   *     auxiliary parameters for proceed call, so this analysis needs the number of parameters
   *     originly declared in around advice
   * @param withReturn if the around adivce has return value
   */
  public ProceedAnalysis(UnitGraph g, int numFormals, boolean withReturn) {

    super(g);
    this.g = g;

    exactProceedSet = new HashSet<Stmt>();
    nonExactProceedSet = new HashSet<Stmt>();

    UnchangedParamsAnalysis paramAnalysis = null;
    // if numformals = 0, dont need paramAnalysis
    if (numFormals >= 0) paramAnalysis = new UnchangedParamsAnalysis(g, numFormals);
    UnchangedReturnAnalysis returnAnalysis = new UnchangedReturnAnalysis(g);
    ExceptionBeforeProceedAnalysis exceptionAnalysis = new ExceptionBeforeProceedAnalysis(g);

    // calcualte exactProceedSet and nonExactProceedSet
    for (Iterator uIt = g.getBody().getUnits().iterator(); uIt.hasNext(); ) {
      Unit unit = (Unit) uIt.next();
      if (unit instanceof Stmt) {
        Stmt s = (Stmt) unit;
        if (withReturn) {
          // care only AssignStmt
          if (s instanceof AssignStmt
              && s.containsInvokeExpr()
              && ImpactUtil.isProceed(((InvokeExpr) s.getInvokeExpr()).getMethod())) {
            boolean exact = false;
            int matchArg = numFormals;
            // if numformals = 0, dont need paramAnalysis analysis
            if (numFormals > 0) {
              matchArg = numMatchArgs(numFormals, paramAnalysis, s);
            }
            // System.out.println("invoke match arg = " + matchArg);
            if (matchArg == numFormals) {
              // should check return value and exceptions
              if (returnAnalysis.isReachReturn(s)) {
                if (!exceptionAnalysis.hasExceptionBefore(s)) {
                  exact = true;
                }
              }
            }
            if (exact) exactProceedSet.add(s);
            else nonExactProceedSet.add(s);
          }
        } else {
          // care only InvokeStmt
          if (s instanceof InvokeStmt
              && s.containsInvokeExpr()
              && ImpactUtil.isProceed(((InvokeExpr) s.getInvokeExpr()).getMethod())) {
            boolean exact = false;
            int matchArg = numFormals;
            // if numformals = 0, dont need paramAnalysis analysis
            if (numFormals > 0) {
              matchArg = numMatchArgs(numFormals, paramAnalysis, s);
            }
            // System.out.println("invoke match arg = " + matchArg);
            if (matchArg == numFormals) {
              // should check exceptions
              if (!exceptionAnalysis.hasExceptionBefore(s)) {
                exact = true;
              }
            }
            if (exact) exactProceedSet.add(s);
            else nonExactProceedSet.add(s);
          }
        }
      }
    }

    doAnalysis();
  }
Beispiel #22
0
  public void assureAllSyncInCallGraph(Collection<JavaCriticalSection> criticalSections) {
    System.out.println("[assureAllSyncInCallgraph] starting");
    Date start = new Date();
    ReachableMethods oldReach = Scene.v().getReachableMethods();
    // Collection et = EntryPoints.v().all();
    // ReachableMethods reachableFromMain = new ReachableMethods(cg, et);
    // reachableFromMain.update();

    Set<SootMethod> notInCG = new HashSet<SootMethod>();
    for (JavaCriticalSection cs : criticalSections) {
      SootMethod m = cs.getSootMethod();
      if (!oldReach.contains(m)) notInCG.add(m);
    }
    Set<SootMethod> alreadyInCG = new HashSet<SootMethod>();
    for (Iterator<MethodOrMethodContext> it = oldReach.listener(); it.hasNext(); ) {
      alreadyInCG.add(it.next().method());
    }
    /*
     * for(Iterator<?> it=cg.sourceMethods();it.hasNext();){ SootMethod m =
     * (SootMethod)it.next(); alreadyInCG.add(m); if(notInCG.contains(m)){
     * notInCG.remove(m); } }
     */

    // add new methods to the call graph
    Stack<SootMethod> worklist = new Stack<SootMethod>();
    for (SootMethod m : notInCG) {
      worklist.push(m);
    }

    while (!worklist.isEmpty()) {
      SootMethod m = worklist.pop();
      if (alreadyInCG.contains(m) || m == null) {
        continue;
      }
      alreadyInCG.add(m);

      Body body = m.retrieveActiveBody();
      for (Unit u : body.getUnits()) {
        if (!(u instanceof Stmt)) {
          continue;
        }

        Stmt s = (Stmt) u;
        if (!s.containsInvokeExpr()) {
          continue;
        }

        InvokeExpr invoke = s.getInvokeExpr();
        SootMethod declCallee = invoke.getMethod();
        Collection<SootMethod> targets = new ArrayList<SootMethod>();
        if (declCallee.isStatic()) {
          targets.add(declCallee);
        } else {
          // XXX: pay attention to reflexive call, thread call, and
          // etc.
          // Here we do not add edges for implicit targets, as these
          // parts of methods is not reachable
          // from the entry, and they will most likely to be analyzed
          // in a very conservative ways.
          InstanceInvokeExpr iie = (InstanceInvokeExpr) invoke;
          Local receiver = (Local) iie.getBase();
          NumberedString subSig = iie.getMethodRef().getSubSignature();

          if (invoke instanceof SpecialInvokeExpr) {
            SootMethod tgt = VirtualCalls.v().resolveSpecial((SpecialInvokeExpr) invoke, subSig, m);
            targets.add(tgt);
          } else {
            Type t = receiver.getType();
            if (t instanceof ArrayType) {
              // t = RefType.v("java.lang.Object");
              targets.add(declCallee);
            }
            // BottomType bug
            else if (t instanceof soot.jimple.toolkits.typing.fast.BottomType) {
              System.out.println("BottomType:" + s);
            } else if (t instanceof soot.NullType) {
              System.out.println("NullType:" + s);
            } else {
              SootClass c = ((RefType) t).getSootClass();
              // Soot has a type resolving bug, and here may be
              // exceptions
              try {
                Set<SootMethod> callees =
                    Scene.v().getOrMakeFastHierarchy().resolveAbstractDispatch(c, declCallee);
                targets.addAll(callees);
              } catch (Exception e) {
                System.out.println(e.getMessage());
              }
            }
          }
        }

        for (SootMethod t : targets) {
          // add call edge
          Edge e = new Edge(m, s, t);
          Scene.v().getCallGraph().addEdge(e);

          // add to worklist
          if (t.isConcrete() && !alreadyInCG.contains(t)) {
            worklist.push(t);
          }
        }
      }
    }

    // infer entries for the methods not reachable from main entry
    List<SootMethod> entries = Scene.v().getEntryPoints();
    _patchedEntries = new ArrayList<SootMethod>(notInCG);
    for (SootMethod m : notInCG) {
      // XXX there can be recursive calls, so for simple processing, all
      // methods not in old
      // call graph should be added to the entry. Checking the
      // non-existence of incoming edges
      // may miss some recursively called methods
      // if(!cg.edgesInto(m).hasNext()){
      entries.add(m);
      // }
    }

    // update reachable methods
    Scene.v().setReachableMethods(null);
  }
Beispiel #23
0
  private static String finegrainedFlowResults() {
    int totalReachableIfs = 0;
    int taintedReachableIfs = 0;

    int totalCountOfTaintSets = 0;
    int totalSizeOfTaintSets = 0;

    long totalValues = 0;

    Set<InfoValue> allSrcs = new HashSet<InfoValue>();
    Set<Set<InfoValue>> allSrcSets = new HashSet<Set<InfoValue>>();

    StringBuffer buf = new StringBuffer();

    for (MethodOrMethodContext momc : PTABridge.v().getReachableMethodContexts()) {
      // reset counted locals for each method
      Set<Value> countedLocals = new HashSet<Value>();

      SootMethod method = momc.method();

      if (!method.isConcrete()) continue;
      try {
        Body body = method.retrieveActiveBody();

        Iterator<Unit> unitIt = body.getUnits().snapshotIterator();

        while (unitIt.hasNext()) {
          Stmt stmt = (Stmt) unitIt.next();

          for (ValueBox vb : stmt.getUseAndDefBoxes()) {
            Value v = vb.getValue();

            if (countedLocals.contains(v)) continue;

            countedLocals.add(v);

            Set<InfoValue> taints = getTaintSet(v, momc);

            if (taints != null) totalValues++;

            if (taints != null && !taints.isEmpty()) {
              allSrcs.addAll(taints);

              totalCountOfTaintSets++;
              totalSizeOfTaintSets += taints.size();

              if (!allSrcSets.contains(taints)) allSrcSets.add(taints);

              countedLocals.add(v);
            }
          }

          if (stmt instanceof IfStmt) {
            totalReachableIfs++;
            boolean hasTainted = false;

            for (ValueBox vb : stmt.getUseBoxes()) {
              Value v = vb.getValue();

              Set<InfoValue> taints = getTaintSet(v, momc);

              if (taints != null && !taints.isEmpty()) {
                hasTainted = true;
                break;
              }
            }

            totalReachableIfs++;

            if (hasTainted) {
              taintedReachableIfs++;
            }
          }
        }

      } catch (Exception e) {
        // ignore and continue
      }
    }

    buf.append("Tainted Reachable if statements: " + taintedReachableIfs + "\n");
    buf.append("Total Reachable if Statements: " + totalReachableIfs + "\n");
    buf.append(
        "Count of non-zero taint sets for primitives and strings: " + totalCountOfTaintSets + "\n");
    buf.append(
        "Total distinct reachable primitives or string values in code: " + totalValues + "\n");
    buf.append(
        "Total size of non-zero taint sets for primitives and strings: "
            + totalSizeOfTaintSets
            + "\n");
    buf.append("Count of distinct sources: " + allSrcs.size() + "\n");
    buf.append("Total distinct source sets: " + allSrcSets.size() + "\n");

    return buf.toString();
  }
 public void flushCollectionCache() {
   super.flushCollectionCache();
 }
 public void flushCache() {
   super.flushCache();
   isDAafter_Variable_values = null;
   isDUafter_Variable_values = null;
   canCompleteNormally_computed = false;
 }
  private static boolean internalAggregate(
      StmtBody body, Map<ValueBox, Zone> boxToZone, boolean onlyStackVars) {
    LocalUses localUses;
    LocalDefs localDefs;
    ExceptionalUnitGraph graph;
    boolean hadAggregation = false;
    Chain<Unit> units = body.getUnits();

    graph = new ExceptionalUnitGraph(body);
    localDefs = new SmartLocalDefs(graph, new SimpleLiveLocals(graph));
    localUses = new SimpleLocalUses(graph, localDefs);

    List<Unit> unitList = new PseudoTopologicalOrderer<Unit>().newList(graph, false);
    for (Unit u : unitList) {
      if (!(u instanceof AssignStmt)) continue;
      AssignStmt s = (AssignStmt) u;

      Value lhs = s.getLeftOp();
      if (!(lhs instanceof Local)) continue;
      Local lhsLocal = (Local) lhs;

      if (onlyStackVars && !lhsLocal.getName().startsWith("$")) continue;

      List<UnitValueBoxPair> lu = localUses.getUsesOf(s);
      if (lu.size() != 1) continue;

      UnitValueBoxPair usepair = lu.get(0);
      Unit use = usepair.unit;
      ValueBox useBox = usepair.valueBox;

      List<Unit> ld = localDefs.getDefsOfAt(lhsLocal, use);
      if (ld.size() != 1) continue;

      // Check to make sure aggregation pair in the same zone
      if (boxToZone.get(s.getRightOpBox()) != boxToZone.get(usepair.valueBox)) {
        continue;
      }

      /* we need to check the path between def and use */
      /* to see if there are any intervening re-defs of RHS */
      /* in fact, we should check that this path is unique. */
      /* if the RHS uses only locals, then we know what
      to do; if RHS has a method invocation f(a, b,
      c) or field access, we must ban field writes, other method
      calls and (as usual) writes to a, b, c. */

      boolean cantAggr = false;
      boolean propagatingInvokeExpr = false;
      boolean propagatingFieldRef = false;
      boolean propagatingArrayRef = false;
      ArrayList<FieldRef> fieldRefList = new ArrayList<FieldRef>();

      LinkedList<Value> localsUsed = new LinkedList<Value>();
      for (ValueBox vb : s.getUseBoxes()) {
        Value v = vb.getValue();
        if (v instanceof Local) localsUsed.add(v);
        else if (v instanceof InvokeExpr) propagatingInvokeExpr = true;
        else if (v instanceof ArrayRef) propagatingArrayRef = true;
        else if (v instanceof FieldRef) {
          propagatingFieldRef = true;
          fieldRefList.add((FieldRef) v);
        }
      }

      // look for a path from s to use in graph.
      // only look in an extended basic block, though.

      List<Unit> path = graph.getExtendedBasicBlockPathBetween(s, use);

      if (path == null) continue;

      Iterator<Unit> pathIt = path.iterator();

      // skip s.
      if (pathIt.hasNext()) pathIt.next();

      while (pathIt.hasNext() && !cantAggr) {
        Stmt between = (Stmt) (pathIt.next());

        if (between != use) {
          // Check for killing definitions

          for (ValueBox vb : between.getDefBoxes()) {
            Value v = vb.getValue();
            if (localsUsed.contains(v)) {
              cantAggr = true;
              break;
            }

            if (propagatingInvokeExpr || propagatingFieldRef || propagatingArrayRef) {
              if (v instanceof FieldRef) {
                if (propagatingInvokeExpr) {
                  cantAggr = true;
                  break;
                } else if (propagatingFieldRef) {
                  // Can't aggregate a field access if passing a definition of a field
                  // with the same name, because they might be aliased
                  for (FieldRef fieldRef : fieldRefList) {
                    if (((FieldRef) v).getField() == fieldRef.getField()) {
                      cantAggr = true;
                      break;
                    }
                  }
                }
              } else if (v instanceof ArrayRef) {
                if (propagatingInvokeExpr) {
                  // Cannot aggregate an invoke expr past an array write
                  cantAggr = true;
                  break;
                } else if (propagatingArrayRef) {
                  // cannot aggregate an array read past a write
                  // this is somewhat conservative
                  // (if types differ they may not be aliased)

                  cantAggr = true;
                  break;
                }
              }
            }
          }

          // Make sure not propagating past a {enter,exit}Monitor
          if (propagatingInvokeExpr && between instanceof MonitorStmt) cantAggr = true;
        }

        // Check for intervening side effects due to method calls
        if (propagatingInvokeExpr || propagatingFieldRef || propagatingArrayRef) {
          for (final ValueBox box : between.getUseBoxes()) {
            if (between == use && box == useBox) {
              // Reached use point, stop looking for
              // side effects
              break;
            }

            Value v = box.getValue();

            if (v instanceof InvokeExpr
                || (propagatingInvokeExpr && (v instanceof FieldRef || v instanceof ArrayRef))) {
              cantAggr = true;
              break;
            }
          }
        }
      }

      // we give up: can't aggregate.
      if (cantAggr) {
        continue;
      }
      /* assuming that the d-u chains are correct, */
      /* we need not check the actual contents of ld */

      Value aggregatee = s.getRightOp();

      if (usepair.valueBox.canContainValue(aggregatee)) {
        boolean wasSimpleCopy = isSimpleCopy(usepair.unit);
        usepair.valueBox.setValue(aggregatee);
        units.remove(s);
        hadAggregation = true;
        // clean up the tags. If s was not a simple copy, the new statement should get
        // the tags of s.
        // OK, this fix was wrong. The condition should not be
        // "If s was not a simple copy", but rather "If usepair.unit
        // was a simple copy". This way, when there's a load of a constant
        // followed by an invoke, the invoke gets the tags.
        if (wasSimpleCopy) {
          // usepair.unit.removeAllTags();
          usepair.unit.addAllTagsOf(s);
        }
      } else {
        /*
        if(Options.v().verbose())
        {
            G.v().out.println("[debug] failed aggregation");
              G.v().out.println("[debug] tried to put "+aggregatee+
                             " into "+usepair.stmt +
                             ": in particular, "+usepair.valueBox);
              G.v().out.println("[debug] aggregatee instanceof Expr: "
                             +(aggregatee instanceof Expr));
        }*/
      }
    }
    return hadAggregation;
  }
Beispiel #27
0
 public void flushCache() {
   super.flushCache();
   canCompleteNormally_computed = false;
 }