Ejemplo n.º 1
0
 /**
  * @param m a method reference
  * @return a SyntheticMethod corresponding to m; or null if none is available.
  */
 protected SyntheticMethod findOrCreateSyntheticMethod(MethodReference m, boolean isStatic) {
   if (syntheticMethods.containsKey(m)) {
     return syntheticMethods.get(m);
   } else {
     MethodSummary summ = null;
     if (canIgnore(m)) {
       TypeReference T = m.getDeclaringClass();
       IClass C = cha.lookupClass(T);
       if (C == null) {
         // did not load class; don't try to create a synthetic method
         syntheticMethods.put(m, null);
         return null;
       }
       summ = generateNoOp(m, isStatic);
     } else {
       summ = findSummary(m);
     }
     if (summ != null) {
       TypeReference T = m.getDeclaringClass();
       IClass C = cha.lookupClass(T);
       if (C == null) {
         syntheticMethods.put(m, null);
         return null;
       }
       SummarizedMethod n = new SummarizedMethod(m, summ, C);
       syntheticMethods.put(m, n);
       return n;
     } else {
       syntheticMethods.put(m, null);
       return null;
     }
   }
 }
Ejemplo n.º 2
0
  @Test
  public void testClassAnnotations3() throws Exception {

    TypeReference typeRef =
        TypeReference.findOrCreate(
            ClassLoaderReference.Application, "Lannotations/AnnotatedClass3");
    IClass klass = cha.lookupClass(typeRef);
    Assert.assertNotNull(klass);
    ShrikeClass shrikeClass = (ShrikeClass) klass;
    Collection<Annotation> classAnnotations = shrikeClass.getAnnotations(true);
    Assert.assertEquals(
        "[Annotation type <Application,Lannotations/AnnotationWithParams> {strParam=classStrParam}]",
        classAnnotations.toString());

    MethodReference methodRefUnderTest =
        MethodReference.findOrCreate(typeRef, Selector.make("foo()V"));

    IMethod methodUnderTest = cha.resolveMethod(methodRefUnderTest);
    Assert.assertNotNull(methodRefUnderTest.toString() + " not found", methodUnderTest);
    Assert.assertTrue(methodUnderTest instanceof ShrikeCTMethod);
    ShrikeCTMethod shrikeCTMethodUnderTest = (ShrikeCTMethod) methodUnderTest;

    Collection<Annotation> runtimeInvisibleAnnotations =
        shrikeCTMethodUnderTest.getAnnotations(true);
    Assert.assertEquals(
        "[Annotation type <Application,Lannotations/AnnotationWithParams> {enumParam=EnumElementValue [type=Lannotations/AnnotationEnum;, val=VAL1], strArrParam=ArrayElementValue [vals=[biz, boz]], annotParam=AnnotationElementValue [type=Lannotations/AnnotationWithSingleParam;, elementValues={value=sdfevs}], strParam=sdfsevs, intParam=25, klassParam=Ljava/lang/Integer;}]",
        runtimeInvisibleAnnotations.toString());
  }
Ejemplo n.º 3
0
 /**
  * @see
  *     com.ibm.wala.ipa.callgraph.propagation.rta.RTAContextInterpreter#understands(com.ibm.wala.ipa.callgraph.CGNode)
  */
 @Override
 public boolean understands(CGNode node) {
   if (node == null) {
     throw new IllegalArgumentException("node is null");
   }
   if (!(node.getContext() instanceof GetMethodContext)) {
     return false;
   }
   MethodReference mRef = node.getMethod().getReference();
   return mRef.equals(GET_METHOD) || mRef.equals(GET_DECLARED_METHOD);
 }
Ejemplo n.º 4
0
 /*
  * @see com.ibm.wala.classLoader.IMethod#getParameterType(int)
  */
 public TypeReference getParameterType(int i) {
   if (isStatic()) {
     return method.getParameterType(i);
   } else {
     if (i == 0) {
       return method.getDeclaringClass();
     } else {
       return method.getParameterType(i - 1);
     }
   }
 }
Ejemplo n.º 5
0
 /**
  * Create statements for methods like getMethod() and getDeclaredMethod(), which return a single
  * method. This creates a return statement for each possible return value, each of which is a
  * {@link ConstantValue} for an {@link IMethod}.
  *
  * @param returnValues the possible return values for this method
  * @return the statements
  */
 private SSAInstruction[] getParticularMethodStatements(
     MethodReference ref,
     Collection<IMethod> returnValues,
     GetMethodContext context,
     Map<Integer, ConstantValue> constants) {
   ArrayList<SSAInstruction> statements = new ArrayList<SSAInstruction>();
   int nextLocal = ref.getNumberOfParameters() + 2;
   IClass cls = context.getType().getType();
   SSAInstructionFactory insts =
       context.getType().getType().getClassLoader().getInstructionFactory();
   if (cls != null) {
     for (IMethod m : returnValues) {
       int c = nextLocal++;
       constants.put(c, new ConstantValue(m));
       SSAReturnInstruction R = insts.ReturnInstruction(statements.size(), c, false);
       statements.add(R);
     }
   } else {
     // SJF: This is incorrect. TODO: fix and enable.
     // SSAThrowInstruction t = insts.ThrowInstruction(retValue);
     // statements.add(t);
   }
   SSAInstruction[] result = new SSAInstruction[statements.size()];
   Iterator<SSAInstruction> it = statements.iterator();
   for (int i = 0; i < result.length; i++) {
     result[i] = it.next();
   }
   return result;
 }
Ejemplo n.º 6
0
/** A {@link ContextSelector} to intercept calls to Object.getClass() */
class GetClassContextSelector implements ContextSelector {

  public static final MethodReference GET_CLASS =
      MethodReference.findOrCreate(TypeReference.JavaLangObject, "getClass", "()Ljava/lang/Class;");

  public GetClassContextSelector() {}

  /*
   * @see com.ibm.wala.ipa.callgraph.ContextSelector#getCalleeTarget(com.ibm.wala.ipa.callgraph.CGNode,
   *      com.ibm.wala.classLoader.CallSiteReference, com.ibm.wala.classLoader.IMethod,
   *      com.ibm.wala.ipa.callgraph.propagation.InstanceKey)
   */
  public Context getCalleeTarget(
      CGNode caller, CallSiteReference site, IMethod callee, InstanceKey[] receiver) {
    if (callee.getReference().equals(GET_CLASS)) {
      return new JavaTypeContext(new PointType(receiver[0].getConcreteType()));
    }
    return null;
  }

  private static final IntSet thisParameter = IntSetUtil.make(new int[] {0});

  public IntSet getRelevantParameters(CGNode caller, CallSiteReference site) {
    if (site.isDispatch() || site.getDeclaredTarget().getNumberOfParameters() > 0) {
      return thisParameter;
    } else {
      return EmptyIntSet.instance;
    }
  }
}
Ejemplo n.º 7
0
 @Override
 public int hashCode() {
   final int prime = 31;
   int result = 1;
   result = prime * result + ((declaringClass == null) ? 0 : declaringClass.hashCode());
   result = prime * result + ((method == null) ? 0 : method.hashCode());
   return result;
 }
Ejemplo n.º 8
0
 @Override
 public String toString() {
   StringBuffer s = new StringBuffer("synthetic ");
   if (isFactoryMethod()) {
     s.append(" factory ");
   }
   s.append(method.toString());
   return s.toString();
 }
Ejemplo n.º 9
0
 /** make main entrypoints, even in the primordial loader. */
 public static Iterable<Entrypoint> makePrimordialMainEntrypoints(
     AnalysisScope scope, ClassHierarchy cha) {
   final Atom mainMethod = Atom.findOrCreateAsciiAtom("main");
   final HashSet<Entrypoint> result = HashSetFactory.make();
   for (IClass klass : cha) {
     MethodReference mainRef =
         MethodReference.findOrCreate(
             klass.getReference(),
             mainMethod,
             Descriptor.findOrCreateUTF8("([Ljava/lang/String;)V"));
     IMethod m = klass.getMethod(mainRef.getSelector());
     if (m != null) {
       result.add(new DefaultEntrypoint(m, cha));
     }
   }
   return new Iterable<Entrypoint>() {
     @Override
     public Iterator<Entrypoint> iterator() {
       return result.iterator();
     }
   };
 }
 /**
  * Add an instruction to invoke the default constructor on the object of value number alloc of
  * type t.
  */
 protected void addCtorInvokeInstruction(final TypeReference t, int alloc) {
   MethodReference init =
       MethodReference.findOrCreate(
           t, MethodReference.initAtom, MethodReference.defaultInitDesc);
   CallSiteReference site =
       CallSiteReference.make(getCallSiteForType(t), init, IInvokeInstruction.Dispatch.SPECIAL);
   int[] params = new int[1];
   params[0] = alloc;
   int exc = getExceptionsForType(t);
   SSAInvokeInstruction s = insts.InvokeInstruction(params, exc, site);
   calls.add(s);
   allInstructions.add(s);
 }
Ejemplo n.º 11
0
 @Override
 public boolean equals(Object obj) {
   if (this == obj) return true;
   if (obj == null) return false;
   if (getClass() != obj.getClass()) return false;
   final SyntheticMethod other = (SyntheticMethod) obj;
   if (declaringClass == null) {
     if (other.declaringClass != null) return false;
   } else if (!declaringClass.equals(other.declaringClass)) return false;
   if (method == null) {
     if (other.method != null) return false;
   } else if (!method.equals(other.method)) return false;
   return true;
 }
Ejemplo n.º 12
0
    /**
     * Add any exceptional edges generated by the last instruction in a basic block.
     *
     * @param last the last instruction in a basic block.
     */
    protected void addExceptionalEdges(IInstruction last) {
      IClassHierarchy cha = getMethod().getClassHierarchy();
      if (last.isPEI()) {
        Collection<TypeReference> exceptionTypes = null;
        boolean goToAllHandlers = false;

        ExceptionHandler[] hs = getExceptionHandlers();
        if (last instanceof ThrowInstruction) {
          // this class does not have the type information needed
          // to determine what the athrow throws. So, add an
          // edge to all reachable handlers. Better information can
          // be obtained later with SSA type propagation.
          // TODO: consider pruning to only the exception types that
          // this method either catches or allocates, since these are
          // the only types that can flow to an athrow.
          goToAllHandlers = true;
        } else {
          if (hs != null && hs.length > 0) {
            IClassLoader loader = getMethod().getDeclaringClass().getClassLoader();
            BytecodeLanguage l = (BytecodeLanguage) loader.getLanguage();
            exceptionTypes = l.getImplicitExceptionTypes(last);
            if (last instanceof IInvokeInstruction) {
              IInvokeInstruction call = (IInvokeInstruction) last;
              exceptionTypes = HashSetFactory.make(exceptionTypes);
              MethodReference target =
                  MethodReference.findOrCreate(
                      l,
                      loader.getReference(),
                      call.getClassType(),
                      call.getMethodName(),
                      call.getMethodSignature());
              try {
                exceptionTypes.addAll(l.inferInvokeExceptions(target, cha));
              } catch (InvalidClassFileException e) {
                e.printStackTrace();
                Assertions.UNREACHABLE();
              }
            }
          }
        }

        if (hs != null && hs.length > 0) {
          // found a handler for this PEI

          // create a mutable copy
          if (!goToAllHandlers) {
            exceptionTypes = HashSetFactory.make(exceptionTypes);
          }

          // this var gets set to false if goToAllHandlers is true but some enclosing exception
          // handler catches all
          // exceptions.  in such a case, we need not add an exceptional edge to the method exit
          boolean needEdgeToExitForAllHandlers = true;
          for (int j = 0; j < hs.length; j++) {
            if (DEBUG) {
              System.err.println(" handler " + hs[j]);
            }
            BasicBlock b = getBlockForInstruction(hs[j].getHandler());
            if (DEBUG) {
              System.err.println(" target " + b);
            }
            if (goToAllHandlers) {
              // add an edge to the catch block.
              if (DEBUG) {
                System.err.println(" gotoAllHandlers " + b);
              }
              addExceptionalEdgeTo(b);
              // if the handler catches all exceptions, we don't need to add an edge to the exit or
              // any other handlers
              if (hs[j].getCatchClass() == null) {
                needEdgeToExitForAllHandlers = false;
                break;
              }
            } else {
              TypeReference caughtException = null;
              if (hs[j].getCatchClass() != null) {
                ClassLoaderReference loader =
                    ShrikeCFG.this.getMethod().getDeclaringClass().getReference().getClassLoader();
                caughtException = ShrikeUtil.makeTypeReference(loader, hs[j].getCatchClass());
                if (DEBUG) {
                  System.err.println(" caughtException " + caughtException);
                }
                IClass caughtClass = cha.lookupClass(caughtException);
                if (caughtClass == null) {
                  // conservatively add the edge, and raise a warning
                  addExceptionalEdgeTo(b);
                  Warnings.add(FailedExceptionResolutionWarning.create(caughtException));
                  // null out caughtException, to avoid attempting to process it
                  caughtException = null;
                }
              } else {
                if (DEBUG) {
                  System.err.println(" catchClass() == null");
                }
                // hs[j].getCatchClass() == null.
                // this means that the handler catches all exceptions.
                // add the edge and null out all types
                if (!exceptionTypes.isEmpty()) {
                  addExceptionalEdgeTo(b);
                  exceptionTypes.clear();
                  caughtException = null;
                }
              }
              if (caughtException != null) {
                IClass caughtClass = cha.lookupClass(caughtException);
                // the set "caught" should be the set of exceptions that MUST
                // have been caught by the handlers in scope
                ArrayList<TypeReference> caught =
                    new ArrayList<TypeReference>(exceptionTypes.size());
                // check if we should add an edge to the catch block.
                for (TypeReference t : exceptionTypes) {
                  if (t != null) {
                    IClass klass = cha.lookupClass(t);
                    if (klass == null) {
                      Warnings.add(FailedExceptionResolutionWarning.create(caughtException));
                      // conservatively add an edge
                      addExceptionalEdgeTo(b);
                    } else {
                      boolean subtype1 = cha.isSubclassOf(klass, caughtClass);
                      if (subtype1 || cha.isSubclassOf(caughtClass, klass)) {
                        // add the edge and null out the type from the array
                        addExceptionalEdgeTo(b);
                        if (subtype1) {
                          caught.add(t);
                        }
                      }
                    }
                  }
                }
                exceptionTypes.removeAll(caught);
              }
            }
          }
          // if needed, add an edge to the exit block.
          if ((exceptionTypes == null && needEdgeToExitForAllHandlers)
              || (exceptionTypes != null && !exceptionTypes.isEmpty())) {
            BasicBlock exit = exit();
            addExceptionalEdgeTo(exit);
          }
        } else {
          // found no handler for this PEI ... link to the exit block.
          BasicBlock exit = exit();
          addExceptionalEdgeTo(exit);
        }
      }
    }
Ejemplo n.º 13
0
 /** @see com.ibm.wala.classLoader.IMethod#isInit() */
 public boolean isInit() {
   return method.getSelector().equals(MethodReference.initSelector);
 }
Ejemplo n.º 14
0
 public Descriptor getDescriptor() {
   return method.getSelector().getDescriptor();
 }
Ejemplo n.º 15
0
 public Atom getName() {
   return method.getSelector().getName();
 }
Ejemplo n.º 16
0
 /** @see com.ibm.wala.classLoader.IMethod#getNumberOfParameters() */
 public int getNumberOfParameters() {
   int n = method.getNumberOfParameters();
   return isStatic() ? n : n + 1;
 }
Ejemplo n.º 17
0
 public static boolean isRemoteProcedure(MethodReference method, IClassHierarchy cha) {
   return isCapsuleInterface(cha.lookupClass(method.getDeclaringClass()));
 }
Ejemplo n.º 18
0
/**
 * Understands {@link com.ibm.wala.analysis.reflection.GetMethodContext}.
 *
 * @author Michael Heilmann
 * @see com.ibm.wala.analysis.reflection.GetMethodContext
 * @see com.ibm.wala.analysis.reflection.GetMethodContextSelector
 */
public class GetMethodContextInterpreter implements SSAContextInterpreter {
  /** TODO MH: Maybe hard-code those in {@link com.ibm.wala.types.MethodReference}? */
  public static final MethodReference GET_METHOD =
      MethodReference.findOrCreate(
          TypeReference.JavaLangClass,
          "getMethod",
          "(Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Method;");

  /** TODO MH: Maybe hard-code those in {@link com.ibm.wala.types.MethodReference}? */
  public static final MethodReference GET_DECLARED_METHOD =
      MethodReference.findOrCreate(
          TypeReference.JavaLangClass,
          "getDeclaredMethod",
          "(Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Method;");

  private static final boolean DEBUG = false;

  /**
   * @see
   *     com.ibm.wala.ipa.callgraph.propagation.SSAContextInterpreter#getIR(com.ibm.wala.ipa.callgraph.CGNode)
   */
  @Override
  public IR getIR(CGNode node) {
    if (node == null) {
      throw new IllegalArgumentException("node is null");
    }
    assert understands(node);
    if (DEBUG) {
      System.err.println("generating IR for " + node);
    }
    IMethod method = node.getMethod();
    GetMethodContext context = (GetMethodContext) node.getContext();
    Map<Integer, ConstantValue> constants = HashMapFactory.make();
    if (method.getReference().equals(GET_METHOD)) {
      Atom name = Atom.findOrCreateAsciiAtom(context.getName());
      SSAInstruction instrs[] = makeGetMethodStatements(context, constants, name);
      return new SyntheticIR(
          method,
          context,
          new InducedCFG(instrs, method, context),
          instrs,
          SSAOptions.defaultOptions(),
          constants);
    }
    if (method.getReference().equals(GET_DECLARED_METHOD)) {
      Atom name = Atom.findOrCreateAsciiAtom(context.getName());
      SSAInstruction instrs[] = makeGetDeclaredMethodStatements(context, constants, name);
      return new SyntheticIR(
          method,
          context,
          new InducedCFG(instrs, method, context),
          instrs,
          SSAOptions.defaultOptions(),
          constants);
    }
    Assertions.UNREACHABLE("Unexpected method " + node);
    return null;
  }

  /**
   * @see
   *     com.ibm.wala.ipa.callgraph.propagation.SSAContextInterpreter#getNumberOfStatements(com.ibm.wala.ipa.callgraph.CGNode)
   */
  @Override
  public int getNumberOfStatements(CGNode node) {
    assert understands(node);
    return getIR(node).getInstructions().length;
  }

  /**
   * @see
   *     com.ibm.wala.ipa.callgraph.propagation.rta.RTAContextInterpreter#understands(com.ibm.wala.ipa.callgraph.CGNode)
   */
  @Override
  public boolean understands(CGNode node) {
    if (node == null) {
      throw new IllegalArgumentException("node is null");
    }
    if (!(node.getContext() instanceof GetMethodContext)) {
      return false;
    }
    MethodReference mRef = node.getMethod().getReference();
    return mRef.equals(GET_METHOD) || mRef.equals(GET_DECLARED_METHOD);
  }

  @Override
  public Iterator<NewSiteReference> iterateNewSites(CGNode node) {
    if (node == null) {
      throw new IllegalArgumentException("node is null");
    }
    assert understands(node);
    GetMethodContext context = (GetMethodContext) node.getContext();
    TypeReference tr = context.getType().getTypeReference();
    if (tr != null) {
      return new NonNullSingletonIterator<NewSiteReference>(NewSiteReference.make(0, tr));
    }
    return EmptyIterator.instance();
  }

  @Override
  public Iterator<CallSiteReference> iterateCallSites(CGNode node) {
    assert understands(node);
    return EmptyIterator.instance();
  }

  /**
   * Get all non-constructor, non-class-initializer methods declared by a class if their name is
   * equal to the specified name.
   *
   * @param cls the class
   * @param name the name
   */
  private Collection<IMethod> getDeclaredNormalMethods(IClass cls, Atom name) {
    Collection<IMethod> result = HashSetFactory.make();
    for (IMethod m : cls.getDeclaredMethods()) {
      if (!m.isInit() && !m.isClinit() && m.getSelector().getName().equals(name)) {
        result.add(m);
      }
    }
    return result;
  }

  /**
   * Get all non-constructor, non-class-initializer methods declared by a class and all its
   * superclasses if their name is equal to the specified name.
   *
   * @param cls the class
   * @param name the name
   */
  private Collection<IMethod> getAllNormalPublicMethods(IClass cls, Atom name) {
    Collection<IMethod> result = HashSetFactory.make();
    Collection<IMethod> allMethods = null;
    allMethods = cls.getAllMethods();
    for (IMethod m : allMethods) {
      if (!m.isInit() && !m.isClinit() && m.isPublic() && m.getSelector().getName().equals(name)) {
        result.add(m);
      }
    }
    return result;
  }

  /**
   * Create statements for methods like getMethod() and getDeclaredMethod(), which return a single
   * method. This creates a return statement for each possible return value, each of which is a
   * {@link ConstantValue} for an {@link IMethod}.
   *
   * @param returnValues the possible return values for this method
   * @return the statements
   */
  private SSAInstruction[] getParticularMethodStatements(
      MethodReference ref,
      Collection<IMethod> returnValues,
      GetMethodContext context,
      Map<Integer, ConstantValue> constants) {
    ArrayList<SSAInstruction> statements = new ArrayList<SSAInstruction>();
    int nextLocal = ref.getNumberOfParameters() + 2;
    IClass cls = context.getType().getType();
    SSAInstructionFactory insts =
        context.getType().getType().getClassLoader().getInstructionFactory();
    if (cls != null) {
      for (IMethod m : returnValues) {
        int c = nextLocal++;
        constants.put(c, new ConstantValue(m));
        SSAReturnInstruction R = insts.ReturnInstruction(statements.size(), c, false);
        statements.add(R);
      }
    } else {
      // SJF: This is incorrect. TODO: fix and enable.
      // SSAThrowInstruction t = insts.ThrowInstruction(retValue);
      // statements.add(t);
    }
    SSAInstruction[] result = new SSAInstruction[statements.size()];
    Iterator<SSAInstruction> it = statements.iterator();
    for (int i = 0; i < result.length; i++) {
      result[i] = it.next();
    }
    return result;
  }

  private SSAInstruction[] makeGetMethodStatements(
      GetMethodContext context, Map<Integer, ConstantValue> constants, Atom name) {
    IClass cls = context.getType().getType();
    if (cls == null) {
      return getParticularMethodStatements(GET_METHOD, null, context, constants);
    } else {
      return getParticularMethodStatements(
          GET_METHOD, getAllNormalPublicMethods(cls, name), context, constants);
    }
  }

  /** Create statements for {@link Class#getDeclaredMethod(String, Class...)}. */
  private SSAInstruction[] makeGetDeclaredMethodStatements(
      GetMethodContext context, Map<Integer, ConstantValue> constants, Atom name) {
    IClass cls = context.getType().getType();
    if (cls == null) {
      return getParticularMethodStatements(GET_DECLARED_METHOD, null, context, constants);
    } else {
      return getParticularMethodStatements(
          GET_DECLARED_METHOD, getDeclaredNormalMethods(cls, name), context, constants);
    }
  }

  @Override
  public boolean recordFactoryType(CGNode node, IClass klass) {
    return false;
  }

  @Override
  public Iterator<FieldReference> iterateFieldsRead(CGNode node) {
    return EmptyIterator.instance();
  }

  @Override
  public Iterator<FieldReference> iterateFieldsWritten(CGNode node) {
    return EmptyIterator.instance();
  }

  @Override
  public ControlFlowGraph<SSAInstruction, ISSABasicBlock> getCFG(CGNode N) {
    return getIR(N).getControlFlowGraph();
  }

  @Override
  public DefUse getDU(CGNode node) {
    return new DefUse(getIR(node));
  }
}