Пример #1
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;
  }
  public boolean DoAnalysis(boolean verbose) {
    Stack<List<Set<SootClass>>> current_exception_sets = new Stack<List<Set<SootClass>>>();
    {
      List<Set<SootClass>> exception_sets = new ArrayList<Set<SootClass>>();
      exception_sets.add(method_exception_set);
      current_exception_sets.push(exception_sets);
    }

    PatchingChain<Unit> chain = body.getUnits();
    Unit next = chain.getFirst();

    int previous_class_count = method_exception_set.size();
    for (Map.Entry<Unit, List<TwoValuePair<Trap, Set<SootClass>>>> entry :
        trap_begin_exception_sets.entrySet()) {
      for (TwoValuePair<Trap, Set<SootClass>> tvp : entry.getValue()) {
        previous_class_count += tvp.w.size();
      }
    }

    do {

      if (trap_begin_exception_sets.containsKey(next)) {
        List<TwoValuePair<Trap, Set<SootClass>>> tvps = trap_begin_exception_sets.get(next);
        List<Set<SootClass>> sets_to_add = new ArrayList<Set<SootClass>>();
        for (TwoValuePair<Trap, Set<SootClass>> tvp : tvps) {
          sets_to_add.add(tvp.w);
        }
        current_exception_sets.push(sets_to_add);
      }
      if (next instanceof InvokeStmt || next instanceof AssignStmt) {
        SootMethod callee = null;

        if (next instanceof AssignStmt) {
          if (((AssignStmt) next).getRightOp() instanceof InvokeExpr) {
            callee = ((InvokeExpr) ((AssignStmt) next).getRightOp()).getMethod();
          }
        } else {
          callee = ((InvokeStmt) next).getInvokeExpr().getMethod();
        }

        if (callee != null) { // invocation only

          Collection<SootClass> exception_classes;
          if (class_map.containsKey(callee.getDeclaringClass())) {
            assert class_map.get(callee.getDeclaringClass()).method_analysis.containsKey(callee);

            exception_classes =
                class_map
                    .get(callee.getDeclaringClass())
                    .method_analysis
                    .get(callee)
                    .method_exception_set;
          } else {
            exception_classes = callee.getExceptions();
          }
          for (SootClass exception_class : exception_classes) {
            for (Set<SootClass> current_exception_set : current_exception_sets.peek()) {
              current_exception_set.add(exception_class);
            }
          }
        }

      } else if (next instanceof ThrowStmt) {

        assert chain.getPredOf(next) instanceof JInvokeStmt;
        assert ((JInvokeStmt) chain.getPredOf(next)).getInvokeExpr() instanceof SpecialInvokeExpr;
        assert ((SpecialInvokeExpr) ((JInvokeStmt) chain.getPredOf(next)).getInvokeExpr()).getBase()
            instanceof JimpleLocal;
        assert ((JimpleLocal)
                    ((SpecialInvokeExpr) ((JInvokeStmt) chain.getPredOf(next)).getInvokeExpr())
                        .getBase())
                .getType()
            instanceof RefType;

        SootClass exception_class =
            ((RefType)
                    ((JimpleLocal)
                            ((SpecialInvokeExpr)
                                    ((JInvokeStmt) chain.getPredOf(next)).getInvokeExpr())
                                .getBase())
                        .getType())
                .getSootClass();

        for (Set<SootClass> current_exception_set : current_exception_sets.peek()) {
          current_exception_set.add(exception_class);
        }
      }

      if (trap_end_exception_sets.containsKey(next)) {

        List<TwoValuePair<Trap, Set<SootClass>>> tvps = trap_end_exception_sets.get(next);

        if (verbose) {
          for (Set<SootClass> current_exception_set : current_exception_sets.peek()) {
            if (current_exception_set.size() == 0) {
              for (TwoValuePair<Trap, Set<SootClass>> tvp : tvps) {
                if (!tvp.v.getException().getName().equals("java.lang.RuntimeException"))
                  System.out.println(
                      "Warning: In "
                          + method.toString()
                          + ": Unncessary exception handler for catching "
                          + tvp.v.getException().getName());
              }
            }
          }
        }

        for (TwoValuePair<Trap, Set<SootClass>> tvp : tvps) {

          Iterator<SootClass> i = tvp.w.iterator();
          while (i.hasNext()) {
            SootClass exception_class = i.next();

            if (tvp.v.getException()
                == exception_class) { // getting properly caught by the handler.
              i.remove();
            } else {
              SootClass super_exception_class = exception_class;
              while (super_exception_class != null) {

                if (tvp.v.getException() == super_exception_class) {
                  i.remove();
                  if (verbose
                      && super_exception_class != exception_class
                      && GetMostRestrictiveFormOfException(tvps, exception_class)
                          == tvp.v.getException()
                      && !super_exception_class.getName().equals("java.lang.RuntimeException")) {
                    System.out.println(
                        "Warning: In "
                            + method.toString()
                            + ": attempting to catch "
                            + exception_class.getName()
                            + " with "
                            + super_exception_class.getName()
                            + " Consider catching the most restrictive exception class");
                  }
                  break;
                }
                try {
                  super_exception_class = super_exception_class.getSuperclass();
                } catch (
                    RuntimeException
                        e) { // unfortunately soot doesn't have a specific exception class for "no
                  // superclass for java.lang.Object" exception
                  super_exception_class = null;
                }
              }
            }
          }
        }

        current_exception_sets.pop();

        for (Set<SootClass> current_exception_set :
            current_exception_sets
                .peek()) { // This list iteration is not necessary if we are still making the
          // assumption that there's only one unique set that contains exception
          // classes if the range for traps are the same
          for (TwoValuePair<Trap, Set<SootClass>> tvp : tvps) {
            for (SootClass exception_class : tvp.w) {
              current_exception_set.add(exception_class);
            }
          }
        }
      }
      next = chain.getSuccOf(next);
    } while (next != null);

    int new_class_count = method_exception_set.size();
    for (Map.Entry<Unit, List<TwoValuePair<Trap, Set<SootClass>>>> entry :
        trap_begin_exception_sets.entrySet()) {
      for (TwoValuePair<Trap, Set<SootClass>> tvp : entry.getValue()) {
        new_class_count += tvp.w.size();
      }
    }

    return new_class_count != previous_class_count;
  }