Example #1
0
  @Test
  public void testClassAnnotations2() throws Exception {
    TypeReference typeUnderTest =
        TypeReference.findOrCreate(
            ClassLoaderReference.Application, "Lannotations/AnnotatedClass2");

    Collection<Annotation> expectedRuntimeInvisibleAnnotations = HashSetFactory.make();
    expectedRuntimeInvisibleAnnotations.add(
        Annotation.make(
            TypeReference.findOrCreate(
                ClassLoaderReference.Application, "Lannotations/RuntimeInvisableAnnotation")));
    expectedRuntimeInvisibleAnnotations.add(
        Annotation.make(
            TypeReference.findOrCreate(
                ClassLoaderReference.Application, "Lannotations/RuntimeInvisableAnnotation2")));

    Collection<Annotation> expectedRuntimeVisibleAnnotations = HashSetFactory.make();
    expectedRuntimeVisibleAnnotations.add(
        Annotation.make(
            TypeReference.findOrCreate(
                ClassLoaderReference.Application, "Lannotations/RuntimeVisableAnnotation")));
    expectedRuntimeVisibleAnnotations.add(
        Annotation.make(
            TypeReference.findOrCreate(
                ClassLoaderReference.Application, "Lannotations/RuntimeVisableAnnotation2")));

    testClassAnnotations(
        typeUnderTest, expectedRuntimeInvisibleAnnotations, expectedRuntimeVisibleAnnotations);
  }
    /**
     * @param t type of object to allocate
     * @return value number of the newly allocated object
     */
    protected int addStatementsForConcreteSimpleType(final TypeReference t) {
      // assert we haven't allocated this type already.
      assert !typesAllocated.contains(t);
      if (DEBUG) {
        System.err.println(("addStatementsForConcreteType: " + t));
      }
      NewSiteReference ref = NewSiteReference.make(getNewSiteForType(t), t);
      int alloc = getLocalForType(t);

      if (t.isArrayType()) {
        // for now, just allocate an array of size 1 in each dimension.
        int dim = t.getDimensionality();
        int[] extents = new int[dim];
        Arrays.fill(extents, 1);
        SSANewInstruction a = insts.NewInstruction(alloc, ref, extents);
        addInstruction(t, a, true);
      } else {
        SSANewInstruction a = insts.NewInstruction(alloc, ref);
        addInstruction(t, a, true);
        addCtorInvokeInstruction(t, alloc);
      }

      SSAReturnInstruction r = insts.ReturnInstruction(alloc, false);
      addInstruction(t, r, false);
      return alloc;
    }
Example #3
0
 /**
  * @return the IClass that represents the innermost array element type, or null if the element
  *     type is a primitive
  */
 public IClass getInnermostElementClass() {
   TypeReference elementType = getReference().getInnermostElementType();
   if (elementType.isPrimitiveType()) {
     return null;
   }
   return loader.lookupClass(elementType.getName());
 }
Example #4
0
  public static TypeReference getCapsuleMockupClassReference(TypeReference capsuleInterface) {
    ClassLoaderReference loader = capsuleInterface.getClassLoader();

    TypeName interfaceName = capsuleInterface.getName();
    String pkg = interfaceName.getPackage().toString();
    String name = interfaceName.getClassName().toString() + CAPSULE_MOCKUP_SUFFIX;

    return TypeReference.findOrCreateClass(loader, pkg, name);
  }
Example #5
0
  /*
   * @see com.ibm.wala.classLoader.IClass#getAllImplementedInterfaces()
   */
  @Override
  public Collection<IClass> getAllImplementedInterfaces() {
    HashSet<IClass> result = HashSetFactory.make(2);
    for (TypeReference ref : getClassLoader().getLanguage().getArrayInterfaces()) {
      IClass klass = loader.lookupClass(ref.getName());
      if (klass != null) {
        result.add(klass);
      }
    }

    return result;
  }
Example #6
0
 /**
  * Package-visible constructor; only for use by ArrayClassLoader class. 'loader' must be the
  * Primordial IClassLoader.
  *
  * <p>[WHY? -- array classes are loaded by the element classloader??]
  */
 ArrayClass(TypeReference type, IClassLoader loader, IClassHierarchy cha) {
   this.type = type;
   this.loader = loader;
   this.cha = cha;
   TypeReference elementType = type.getInnermostElementType();
   if (!elementType.isPrimitiveType()) {
     IClass klass = loader.lookupClass(elementType.getName());
     if (klass == null) {
       Assertions.UNREACHABLE("caller should not attempt to create an array with type " + type);
     }
   } else {
     // assert loader.getReference().equals(ClassLoaderReference.Primordial);
   }
 }
Example #7
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());
  }
    @Override
    public void visitJavaScriptInvoke(JavaScriptInvoke invk) {
      // check whether this instruction corresponds to a function expression/declaration
      if (isFunctionConstructorInvoke(invk)) {
        int defn = invk.getDef();

        // the name of the function
        String fnName = symtab.getStringValue(invk.getUse(1));
        IClass fnClass =
            cha.lookupClass(TypeReference.findOrCreate(JavaScriptTypes.jsLoader, fnName));
        if (fnClass == null) {
          System.err.println(
              "cannot find " + fnName + " at " + ((AstMethod) method).getSourcePosition());
          return;
        }
        IMethod fn = fnClass.getMethod(AstMethodReference.fnSelector);
        FuncVertex callee = factory.makeFuncVertex(fnClass);

        // look at all uses
        for (Iterator<SSAInstruction> uses = du.getUses(defn); uses.hasNext(); ) {
          SSAInstruction use = uses.next();

          // check whether this is a local call
          if (use instanceof JavaScriptInvoke && ((JavaScriptInvoke) use).getFunction() == defn) {
            JavaScriptInvoke use_invk = (JavaScriptInvoke) use;

            // yes, so add edges from arguments to parameters...
            for (int i = 2; i < use_invk.getNumberOfParameters(); ++i)
              flowgraph.addEdge(
                  factory.makeVarVertex(caller, use_invk.getUse(i)),
                  factory.makeParamVertex(callee, i - 1));

            // ...and from return to result
            flowgraph.addEdge(
                factory.makeRetVertex(callee), factory.makeVarVertex(caller, use.getDef()));

            // note: local calls are never qualified, so there is no flow into the receiver vertex
          } else {
            // no, it's a more complicated use, so add flows from/to unknown
            for (int i = 1; i < fn.getNumberOfParameters(); ++i)
              flowgraph.addEdge(factory.makeUnknownVertex(), factory.makeParamVertex(callee, i));
            flowgraph.addEdge(factory.makeRetVertex(callee), factory.makeUnknownVertex());
          }
        }
      } else {
        // this is a genuine function call; find out where the function came from
        SSAInstruction def = du.getDef(invk.getFunction());

        // if it's not a local call, add flows from/to unknown
        if (!(def instanceof JavaScriptInvoke)
            || !isFunctionConstructorInvoke((JavaScriptInvoke) def)) {
          for (int i = 1; i < invk.getNumberOfParameters(); ++i)
            flowgraph.addEdge(
                factory.makeVarVertex(caller, invk.getUse(i)), factory.makeUnknownVertex());
          flowgraph.addEdge(
              factory.makeUnknownVertex(), factory.makeVarVertex(caller, invk.getDef()));
        }
      }
    }
 /**
  * @param type
  * @return a TypeAbstraction object representing this type. We just use ConeTypes by default,
  *     since we don't propagate information allowing us to distinguish between points and cones
  *     yet.
  */
 protected TypeAbstraction typeRef2TypeAbstraction(IClassHierarchy cha, TypeReference type) {
   IClass klass = cha.lookupClass(type);
   if (klass != null) {
     return new ConeType(klass);
   }
   Assertions.UNREACHABLE(type.toString());
   return null;
 }
Example #10
0
 @Override
 public boolean equals(Object obj) {
   if (obj instanceof ArrayClass) {
     ArrayClass other = (ArrayClass) obj;
     return loader.equals(other.loader) && type.equals(other.type);
   } else {
     return false;
   }
 }
 private boolean allFieldsArePrimitive(IClass c) {
   if (c.isArrayClass()) {
     TypeReference t = c.getReference().getArrayElementType();
     return t.isPrimitiveType();
   } else {
     if (c.getReference().equals(TypeReference.JavaLangObject)) {
       return true;
     } else {
       for (Iterator<IField> it = c.getDeclaredInstanceFields().iterator(); it.hasNext(); ) {
         IField f = it.next();
         if (f.getReference().getFieldType().isReferenceType()) {
           return false;
         }
       }
       return allFieldsArePrimitive(c.getSuperclass());
     }
   }
 }
Example #12
0
  /*
   * @see com.ibm.wala.classLoader.IClass#getSuperclass()
   */
  @Override
  public IClass getSuperclass() {
    IClass elt = getElementClass();
    assert getReference().getArrayElementType().isPrimitiveType() || elt != null;

    // super is Ljava/lang/Object in two cases:
    // 1) [Ljava/lang/Object
    // 2) [? for primitive arrays (null from getElementClass)
    if (elt == null || elt.getReference() == getClassLoader().getLanguage().getRootType()) {
      return loader.lookupClass(getClassLoader().getLanguage().getRootType().getName());
    }

    // else it is array of super of element type (yuck)
    else {
      TypeReference eltSuperRef = elt.getSuperclass().getReference();
      TypeReference superRef = TypeReference.findOrCreateArrayOf(eltSuperRef);
      return elt.getSuperclass().getClassLoader().lookupClass(superRef.getName());
    }
  }
Example #13
0
  @Override
  public IMethod getCalleeTarget(CGNode caller, CallSiteReference site, IClass receiver) {
    IMethod target = base.getCalleeTarget(caller, site, receiver);
    if (target != null && target.getReference().equals(loadFileFunRef)) {

      Set<String> names = new HashSet<String>();
      SSAInstruction call =
          caller.getIR()
              .getInstructions()[
              caller.getIR().getCallInstructionIndices(site).intIterator().next()];
      if (call.getNumberOfUses() > 1) {
        LocalPointerKey fileNameV = new LocalPointerKey(caller, call.getUse(1));
        OrdinalSet<InstanceKey> ptrs = builder.getPointerAnalysis().getPointsToSet(fileNameV);
        for (InstanceKey k : ptrs) {
          if (k instanceof ConstantKey) {
            Object v = ((ConstantKey) k).getValue();
            if (v instanceof String) {
              names.add((String) v);
            }
          }
        }

        if (names.size() == 1) {
          String str = names.iterator().next();
          try {
            JavaScriptLoader cl =
                (JavaScriptLoader) builder.getClassHierarchy().getLoader(JavaScriptTypes.jsLoader);
            URL url = new URL(builder.getBaseURL(), str);
            if (!loadedFiles.contains(url)) {
              // try to open the input stream for the URL.  if it fails, we'll get an IOException
              // and fall through to default case
              InputStream inputStream = url.openConnection().getInputStream();
              inputStream.close();
              JSCallGraphUtil.loadAdditionalFile(builder.getClassHierarchy(), cl, url);
              loadedFiles.add(url);
              IClass script =
                  builder
                      .getClassHierarchy()
                      .lookupClass(
                          TypeReference.findOrCreate(cl.getReference(), "L" + url.getFile()));
              return script.getMethod(JavaScriptMethods.fnSelector);
            }
          } catch (MalformedURLException e1) {
            // do nothing, fall through and return 'target'
          } catch (IOException e) {
            // do nothing, fall through and return 'target'
          } catch (RuntimeException e) {
            // do nothing, fall through and return 'target'
          }
        }
      }
    }

    return target;
  }
Example #14
0
  protected void doNewObject(
      WalkContext context, CAstNode newNode, int result, Object type, int[] arguments) {
    assert arguments == null;
    TypeReference typeRef =
        TypeReference.findOrCreate(JavaScriptTypes.jsLoader, TypeName.string2TypeName("L" + type));

    context
        .cfg()
        .addInstruction(
            insts.NewInstruction(
                result, NewSiteReference.make(context.cfg().getCurrentInstruction(), typeRef)));
  }
Example #15
0
 /**
  * @param reference a type reference for an array type
  * @return the dimensionality of the array
  */
 public static int getArrayTypeDimensionality(TypeReference reference) {
   int mask = reference.getDerivedMask();
   if ((mask & PrimitiveMask) == PrimitiveMask) {
     mask >>= ElementBits;
   }
   int dims = 0;
   while ((mask & ArrayMask) == ArrayMask) {
     mask >>= ElementBits;
     dims++;
   }
   assert dims > 0;
   return dims;
 }
Example #16
0
 protected void addFieldToList(
     List<FieldImpl> L,
     Atom name,
     ImmutableByteArray fieldType,
     int accessFlags,
     Collection<Annotation> annotations) {
   TypeName T = null;
   if (fieldType.get(fieldType.length() - 1) == ';') {
     T = TypeName.findOrCreate(fieldType, 0, fieldType.length() - 1);
   } else {
     T = TypeName.findOrCreate(fieldType);
   }
   TypeReference type = TypeReference.findOrCreate(getClassLoader().getReference(), T);
   FieldReference fr = FieldReference.findOrCreate(getReference(), name, type);
   FieldImpl f = new FieldImpl(this, fr, accessFlags, annotations);
   L.add(f);
 }
Example #17
0
  private void testClassAnnotations(
      TypeReference typeUnderTest,
      Collection<Annotation> expectedRuntimeInvisibleAnnotations,
      Collection<Annotation> expectedRuntimeVisibleAnnotations)
      throws IOException, ClassHierarchyException, InvalidClassFileException {
    IClass classUnderTest = cha.lookupClass(typeUnderTest);
    Assert.assertNotNull(typeUnderTest.toString() + " not found", classUnderTest);
    Assert.assertTrue(classUnderTest instanceof ShrikeClass);
    ShrikeClass shrikeClassUnderTest = (ShrikeClass) classUnderTest;

    Collection<Annotation> runtimeInvisibleAnnotations =
        shrikeClassUnderTest.getRuntimeInvisibleAnnotations();
    assertEqualCollections(expectedRuntimeInvisibleAnnotations, runtimeInvisibleAnnotations);

    Collection<Annotation> runtimeVisibleAnnotations =
        shrikeClassUnderTest.getRuntimeVisibleAnnotations();
    assertEqualCollections(expectedRuntimeVisibleAnnotations, runtimeVisibleAnnotations);
  }
Example #18
0
 @Override
 public int hashCode() {
   return type.hashCode();
 }
Example #19
0
 public String getQualifiedNameForReflection() {
   return type.getName().toString(); // XXX is this the right string?
 }
Example #20
0
  private static Result getOrigSDG(Config cfg, IProgressMonitor progress)
      throws IllegalArgumentException, CancelException, PDGFormatException, IOException,
          WalaException, InvalidClassFileException {
    progress.beginTask(Messages.getString("Analyzer.Task_Prepare_IR"), -1); // $NON-NLS-1$

    com.ibm.wala.ipa.callgraph.impl.Util.setNativeSpec(cfg.nativesXML);

    progress.subTask(Messages.getString("Analyzer.SubTask_Analysis_Scope")); // $NON-NLS-1$

    ClassLoader loader = cfg.getClass().getClassLoader();
    AnalysisScope scope = Util.makeAnalysisScope(cfg, loader);
    // AnalysisScopeReader.makeJavaBinaryAnalysisScope(cfg.scopeFile, cfg.classpath, null);
    progress.done();

    ClassHierarchy cha = ClassHierarchy.make(scope, progress);

    Iterable<Entrypoint> entrypoints =
        com.ibm.wala.ipa.callgraph.impl.Util.makeMainEntrypoints(scope, cha, cfg.mainClass);
    AnalysisOptions options = new AnalysisOptions(scope, entrypoints);
    AnalysisCache cache = new AnalysisCache();

    progress.subTask(
        Messages.getString("Analyzer.SubTask_Call_Graph_Builder") + cfg.pointsTo); // $NON-NLS-1$
    SSAPropagationCallGraphBuilder builder =
        SDGFactory.getCallGraphBuilder(cfg.pointsTo, options, cache, cha, scope);

    /**
     * Change the wala internal pointer and instancekeyfactory of the callgraph builder to our
     * adapter. So we can keep track of the created InstanceKeys and PointerKeys. This information
     * is used later on when creating subobject trees for accessed field variables.
     */
    InstanceAndPointerKeyFactoryAdapter adapter = null;
    InstanceKeyFactory ikFact = builder.getInstanceKeys();
    PointerKeyFactory pkFact = builder.getPointerKeyFactory();
    adapter = new InstanceAndPointerKeyFactoryAdapter(ikFact, pkFact);

    builder.setInstanceKeys(adapter);
    builder.setPointerKeyFactory(adapter);

    progress.done();

    progress.subTask(Messages.getString("Analyzer.SubTask_Call_Graph")); // $NON-NLS-1$
    CallGraph cg = builder.makeCallGraph(options, progress);

    if (cfg.optimizeCg >= 0) {
      CallGraphPruning opt = new CallGraphPruning(cg);
      System.out.println("Call Graph has " + cg.getNumberOfNodes() + " Nodes.");
      Set<CGNode> sopt = opt.findApplicationNodes(cfg.optimizeCg);
      cg = new PrunedCallGraph(cg, sopt);
      System.out.println("Optimized Call Graph has " + cg.getNumberOfNodes() + " Nodes.");
    }

    if (Debug.Var.DUMP_CALLGRAPH.isSet()) {
      Util.dumpCallGraph(cg, cfg.mainClass.replace('/', '.').substring(1), progress);
    }

    if (Debug.Var.DUMP_HEAP_GRAPH.isSet()) {
      PointerAnalysis pta = builder.getPointerAnalysis();
      HeapGraph hg = pta.getHeapGraph();
      Util.dumpHeapGraph(
          cfg.mainClass.replace('/', '.').substring(1) + "." + cfg.pointsTo, hg, null);
    }

    PointerAnalysis pta = builder.getPointerAnalysis();
    progress.done();

    DemandRefinementPointsTo demandPts = null;
    if (cfg.useDemandPts) {
      throw new UnsupportedOperationException();
      //		    MemoryAccessMap mam = new PABasedMemoryAccessMap(cg, builder.getPointerAnalysis());
      //			demandPts = new DemandRefinementPointsTo(cg,
      //				new ThisFilteringHeapModel(builder,cha), mam, cha, options, getStateMachineFactory());
    }

    IPointerAnalysis pts = new PointsToWrapper(demandPts, pta);

    progress.subTask(Messages.getString("Analyzer.SubTask_Search_Main")); // $NON-NLS-1$
    IMethod main =
        edu.kit.joana.deprecated.jsdg.util.Util.searchMethod(
            entrypoints, "main([Ljava/lang/String;)V"); // $NON-NLS-1$
    progress.done();

    progress.done();

    SDG sdg = SDG.create(main, cg, cache, adapter, pts, cfg, progress);
    sdg.setAnalysisScope(scope);
    sdg.setPointerAnalysis(pta);

    progress.done();

    if (Debug.Var.PRINT_FIELD_PTS_INFO.isSet()) {
      Log.info("search for field allocs called " + PDG.searchFieldAllocs + " times.");
    }

    if (Debug.Var.PRINT_UNRESOLVED_CLASSES.isSet()) {
      for (TypeReference tRef : cg.getClassHierarchy().getUnresolvedClasses()) {
        Log.warn("Could not resolve: " + Util.typeName(tRef.getName()));
      }
    }

    return new Result(null, sdg, cg, pta, null);
  }
 private boolean isReflectiveType(TypeReference type) {
   return type.equals(TypeReference.JavaLangReflectConstructor)
       || type.equals(TypeReference.JavaLangReflectMethod);
 }
Example #22
0
  private void run(IProgressMonitor progress) throws CancelException {
    final Map<PDGNode, PDGNode[]> entry2out = new HashMap<PDGNode, PDGNode[]>();

    // add out nodes for each non-primitive parameter
    for (final PDG pdg : sdg.getAllPDGs()) {
      // primitive types nodes are null
      final PDGNode[] formOuts = new PDGNode[pdg.params.length];

      for (int i = 0; i < pdg.params.length; i++) {
        final PDGNode formIn = pdg.params[i];
        final TypeReference type = pdg.getParamType(i);

        if (createOutputParamFor(type)) {
          final PDGNode formOut =
              pdg.addOutputFieldChildTo(
                  pdg.entry,
                  formIn.getLabel(),
                  formIn.getBytecodeName(),
                  formIn.getBytecodeIndex(),
                  formIn.getTypeRef());
          formOuts[i] = formOut;
        }
      }

      entry2out.put(pdg.entry, formOuts);

      for (final PDGNode call : pdg.getCalls()) {
        final PDGNode[] actIns = pdg.getParamIn(call);
        final PDGNode[] actOuts = new PDGNode[actIns.length];

        for (int i = 0; i < actIns.length; i++) {
          final PDGNode actIn = actIns[i];
          final TypeReference type = pdg.getParamType(call, i);

          if (createOutputParamFor(type)) {
            final PDGNode actOut =
                pdg.addOutputFieldChildTo(
                    call,
                    actIn.getLabel(),
                    actIn.getBytecodeName(),
                    actIn.getBytecodeIndex(),
                    actIn.getTypeRef());
            actOuts[i] = actOut;
          }
        }

        entry2out.put(call, actOuts);
      }
    }

    // connect form-outs of called procedures with act-outs
    for (final PDG pdg : sdg.getAllPDGs()) {
      for (final PDGNode call : pdg.getCalls()) {
        final PDGNode[] actOuts = entry2out.get(call);
        assert actOuts != null;

        for (final PDGEdge out : pdg.outgoingEdgesOf(call)) {
          if (out.kind == PDGEdge.Kind.CALL_STATIC || out.kind == PDGEdge.Kind.CALL_VIRTUAL) {
            final PDGNode calleeEntry = out.to;
            final PDGNode[] formOuts = entry2out.get(calleeEntry);
            final PDG callee = sdg.getPDGforId(calleeEntry.getPdgId());
            assert formOuts != null;
            assert actOuts.length == formOuts.length;

            for (int i = 0; i < actOuts.length; i++) {
              final PDGNode actOut = actOuts[i];
              if (actOut != null) {
                // primitive type (and immutable type) params have no act out
                callee.addVertex(actOut);
                final PDGNode formOut = formOuts[i];

                if (formOut != null) {
                  callee.addEdge(formOut, actOut, PDGEdge.Kind.PARAMETER_OUT);
                }
              }
            }
          }
        }
      }
    }

    // collect reachable points-to elements for reachable fields for each parameter
    for (final PDG pdg : sdg.getAllPDGs()) {
      final Map<PDGNode, OrdinalSet<InstanceKey>> node2ptsMod =
          new HashMap<PDGNode, OrdinalSet<InstanceKey>>();
      final Map<PDGNode, OrdinalSet<InstanceKey>> node2ptsRef =
          new HashMap<PDGNode, OrdinalSet<InstanceKey>>();

      final IR ir = pdg.cgNode.getIR();

      if (ir == null) {
        continue;
      }

      for (int i = 0; i < pdg.params.length; i++) {
        if (!pdg.getParamType(i).isPrimitiveType()) {
          final PDGNode formIn = pdg.params[i];
          final int ssaVar = ir.getParameter(i);

          if (ssaVar >= 0) {
            final OrdinalSet<InstanceKey> ptsSet = findReachableInstances(pdg.cgNode, ssaVar);
            node2ptsMod.put(formIn, ptsSet);
          }
        }
      }

      final PDGNode[] formOuts = entry2out.get(pdg.entry);
      for (int i = 0; i < formOuts.length; i++) {
        final PDGNode formOut = formOuts[i];

        if (formOut != null) {
          final PDGNode formIn = pdg.params[i];
          final OrdinalSet<InstanceKey> ptsSet = node2ptsMod.get(formIn);
          node2ptsRef.put(formOut, ptsSet);
        }
      }

      final TypeReference retType = pdg.getMethod().getReturnType();
      if (retType != TypeReference.Void && !retType.isPrimitiveType()) {
        for (final PDGNode retNode : pdg.getReturns()) {
          final SSAReturnInstruction ret = (SSAReturnInstruction) pdg.getInstruction(retNode);
          final int ssaVar = ret.getResult();
          final OrdinalSet<InstanceKey> ptsSet = findReachableInstances(pdg.cgNode, ssaVar);

          node2ptsRef.put(retNode, ptsSet);
        }
      }

      for (final PDGNode call : pdg.getCalls()) {
        final PDGNode[] actIns = pdg.getParamIn(call);

        final SSAAbstractInvokeInstruction invk =
            (SSAAbstractInvokeInstruction) pdg.getInstruction(call);

        for (int i = 0; i < actIns.length; i++) {

          if (!pdg.getParamType(call, i).isPrimitiveType()) {
            final PDGNode actIn = actIns[i];
            final int ssaVar = invk.getUse(i);

            if (ssaVar >= 0) {
              final OrdinalSet<InstanceKey> ptsSet = findReachableInstances(pdg.cgNode, ssaVar);
              node2ptsRef.put(actIn, ptsSet);
            }
          }
        }

        final PDGNode actOuts[] = entry2out.get(call);
        for (int i = 0; i < actIns.length; i++) {
          final PDGNode actOut = actOuts[i];

          if (actOut != null) {
            final PDGNode actIn = actIns[i];
            final OrdinalSet<InstanceKey> ptsSet = node2ptsRef.get(actIn);
            node2ptsMod.put(actOut, ptsSet);
          }
        }

        final TypeReference callRetType = invk.getDeclaredTarget().getReturnType();
        if (callRetType != TypeReference.Void && !callRetType.isPrimitiveType()) {
          final int ssaVar = invk.getReturnValue(0);
          final OrdinalSet<InstanceKey> ptsSet = findReachableInstances(pdg.cgNode, ssaVar);
          final PDGNode retNode = pdg.getReturnOut(call);
          node2ptsMod.put(retNode, ptsSet);
        }
      }

      // create mod/ref sets for get & set instructions
      for (final PDGField read : pdg.getFieldReads()) {
        if (!read.field.isStatic()) {
          if (read.field.isArray()) {
            final SSAArrayLoadInstruction ali =
                (SSAArrayLoadInstruction) pdg.getInstruction(read.node);
            final int ssaVarBase = ali.getArrayRef();

            if (ssaVarBase >= 0) {
              final OrdinalSet<InstanceKey> ptsSet = pointsToArrayField(pdg.cgNode, ssaVarBase);
              node2ptsRef.put(read.accfield, ptsSet);
            }
          } else {
            final SSAGetInstruction get = (SSAGetInstruction) pdg.getInstruction(read.node);
            final int ssaVarBase = get.getRef();

            if (ssaVarBase >= 0) {
              final IField field = sdg.getClassHierarchy().resolveField(get.getDeclaredField());
              final OrdinalSet<InstanceKey> ptsSet =
                  pointsToObjectField(pdg.cgNode, ssaVarBase, field);
              node2ptsRef.put(read.accfield, ptsSet);
            }
          }

          //					final SSAInstruction get = pdg.getInstruction(read.node);
          //					final int ssaVar = get.getDef();
          //					if (ssaVar >= 0) {
          //						final OrdinalSet<InstanceKey> ptsSet = findReachableInstances(pdg.cgNode, ssaVar);
          //						node2ptsRef.put(read.accfield, ptsSet);
          //					}
        }
      }

      for (final PDGField write : pdg.getFieldWrites()) {
        if (!write.field.isStatic()) {
          if (write.field.isArray()) {
            final SSAArrayStoreInstruction asi =
                (SSAArrayStoreInstruction) pdg.getInstruction(write.node);
            final int ssaVarBase = asi.getArrayRef();

            if (ssaVarBase >= 0) {
              final OrdinalSet<InstanceKey> ptsSet = pointsToArrayField(pdg.cgNode, ssaVarBase);
              node2ptsMod.put(write.accfield, ptsSet);
            }
          } else {
            final SSAPutInstruction put = (SSAPutInstruction) pdg.getInstruction(write.node);
            final int ssaVarBase = put.getRef();

            if (ssaVarBase >= 0) {
              final IField field = sdg.getClassHierarchy().resolveField(put.getDeclaredField());
              final OrdinalSet<InstanceKey> ptsSet =
                  pointsToObjectField(pdg.cgNode, ssaVarBase, field);
              node2ptsMod.put(write.accfield, ptsSet);
            }
          }
        }
      }

      // add data flow for each pdg
      FlatHeapParamsDataFlow.compute(
          pdg,
          node2ptsMod,
          node2ptsRef,
          (sdg.cfg.accessPath ? PDGEdge.Kind.DATA_ALIAS : PDGEdge.Kind.DATA_HEAP),
          progress);
    }
  }
Example #23
0
 public static boolean isKnownSafeTypeForTransfer(TypeReference typeRef) {
   // TODO: Add String and primitive box types (e.g. Integer).
   return typeRef.isPrimitiveType();
 }
/**
 * Flexible class to create {@link InstanceKey}s depending on various policies ranging from
 * class-based (i.e. 0-CFA) to allocation-site-based (0-1-CFA variants).
 */
public class ZeroXInstanceKeys implements InstanceKeyFactory {

  private static final TypeName JavaLangStringBufferName =
      TypeName.string2TypeName("Ljava/lang/StringBuffer");

  public static final TypeReference JavaLangStringBuffer =
      TypeReference.findOrCreate(ClassLoaderReference.Primordial, JavaLangStringBufferName);

  private static final TypeName JavaLangStringBuilderName =
      TypeName.string2TypeName("Ljava/lang/StringBuilder");

  public static final TypeReference JavaLangStringBuilder =
      TypeReference.findOrCreate(ClassLoaderReference.Primordial, JavaLangStringBuilderName);

  private static final TypeName JavaLangAbstractStringBuilderName =
      TypeName.string2TypeName("Ljava/lang/AbstractStringBuilder");

  public static final TypeReference JavaLangAbstractStringBuilder =
      TypeReference.findOrCreate(
          ClassLoaderReference.Primordial, JavaLangAbstractStringBuilderName);

  /** The NONE policy is not allocation-site based */
  public static final int NONE = 0;

  /**
   * An ALLOCATIONS - based policy distinguishes instances by allocation site. Otherwise, the policy
   * distinguishes instances by type.
   */
  public static final int ALLOCATIONS = 1;

  /**
   * A policy variant where String and StringBuffers are NOT disambiguated according to allocation
   * site.
   */
  public static final int SMUSH_STRINGS = 2;

  /**
   * A policy variant where {@link Throwable} instances are NOT disambiguated according to
   * allocation site.
   */
  public static final int SMUSH_THROWABLES = 4;

  /**
   * A policy variant where if a type T has only primitive instance fields, then instances of type T
   * are NOT disambiguated by allocation site.
   */
  public static final int SMUSH_PRIMITIVE_HOLDERS = 8;

  /**
   * This variant counts the N, number of allocation sites of a particular type T in each method. If
   * N > SMUSH_LIMIT, then these N allocation sites are NOT distinguished ... instead there is a
   * single abstract allocation site for <N,T>
   *
   * <p>Probably the best choice in many cases.
   */
  public static final int SMUSH_MANY = 16;

  /** Should we use constant-specific keys? */
  public static final int CONSTANT_SPECIFIC = 32;

  /** When using smushing, how many sites in a node will be kept distinct before smushing? */
  private final int SMUSH_LIMIT = 25;

  /** The policy choice for instance disambiguation */
  private final int policy;

  /** A delegate object to create class-based abstract instances */
  private final ClassBasedInstanceKeys classBased;

  /** A delegate object to create allocation site-based abstract instances */
  private final AllocationSiteInNodeFactory siteBased;

  /** A delegate object to create "abstract allocation site" - based abstract instances */
  private final SmushedAllocationSiteInstanceKeys smushed;

  /** The governing class hierarchy */
  private final IClassHierarchy cha;

  /** An object which interprets nodes in context. */
  private final RTAContextInterpreter contextInterpreter;

  /** a Map from CGNode->Set<IClass> that should be smushed. */
  protected final Map<CGNode, Set<IClass>> smushMap = HashMapFactory.make();

  public ZeroXInstanceKeys(
      AnalysisOptions options,
      IClassHierarchy cha,
      RTAContextInterpreter contextInterpreter,
      int policy) {
    if (options == null) {
      throw new IllegalArgumentException("null options");
    }
    this.policy = policy;
    if (disambiguateConstants()) {
      // this is an ugly hack. TODO: clean it all up.
      options.setUseConstantSpecificKeys(true);
    }
    classBased = new ClassBasedInstanceKeys(options, cha);
    siteBased = new AllocationSiteInNodeFactory(options, cha);
    smushed = new SmushedAllocationSiteInstanceKeys(options, cha);
    this.cha = cha;
    this.contextInterpreter = contextInterpreter;
  }

  /** @return true iff the policy smushes some allocation sites */
  private boolean smushMany() {
    return (policy & SMUSH_MANY) > 0;
  }

  private boolean allocationPolicy() {
    return (policy & ALLOCATIONS) > 0;
  }

  private boolean smushStrings() {
    return (policy & SMUSH_STRINGS) > 0;
  }

  public boolean smushThrowables() {
    return (policy & SMUSH_THROWABLES) > 0;
  }

  private boolean smushPrimHolders() {
    return (policy & SMUSH_PRIMITIVE_HOLDERS) > 0;
  }

  public boolean disambiguateConstants() {
    return (policy & CONSTANT_SPECIFIC) > 0;
  }

  public InstanceKey getInstanceKeyForAllocation(CGNode node, NewSiteReference allocation) {
    if (allocation == null) {
      throw new IllegalArgumentException("allocation is null");
    }
    TypeReference t = allocation.getDeclaredType();
    IClass C = cha.lookupClass(t);

    if (C != null && isInteresting(C)) {
      if (smushMany()) {
        if (exceedsSmushLimit(C, node)) {
          return smushed.getInstanceKeyForAllocation(node, allocation);
        } else {
          return siteBased.getInstanceKeyForAllocation(node, allocation);
        }
      } else {
        return siteBased.getInstanceKeyForAllocation(node, allocation);
      }
    } else {
      return classBased.getInstanceKeyForAllocation(node, allocation);
    }
  }

  /**
   * side effect: populates the smush map.
   *
   * @return true iff the node contains too many allocation sites of type c
   */
  private boolean exceedsSmushLimit(IClass c, CGNode node) {
    Set<IClass> s = smushMap.get(node);
    if (s == null) {
      Map<IClass, Integer> count = countAllocsByType(node);
      HashSet<IClass> smushees = HashSetFactory.make(5);
      for (Iterator<Map.Entry<IClass, Integer>> it = count.entrySet().iterator(); it.hasNext(); ) {
        Map.Entry<IClass, Integer> e = it.next();
        Integer i = e.getValue();
        if (i.intValue() > SMUSH_LIMIT) {
          smushees.add(e.getKey());
        }
      }
      s = smushees.isEmpty() ? Collections.<IClass>emptySet() : smushees;
      smushMap.put(node, s);
    }
    return s.contains(c);
  }

  /** @return Map: IClass -> Integer, the number of allocation sites for each type. */
  private Map<IClass, Integer> countAllocsByType(CGNode node) {
    Map<IClass, Integer> count = HashMapFactory.make();
    for (Iterator it = contextInterpreter.iterateNewSites(node); it.hasNext(); ) {
      NewSiteReference n = (NewSiteReference) it.next();
      IClass alloc = cha.lookupClass(n.getDeclaredType());
      if (alloc != null) {
        Integer old = count.get(alloc);
        if (old == null) {
          count.put(alloc, new Integer(1));
        } else {
          count.put(alloc, new Integer(old.intValue() + 1));
        }
      }
    }
    return count;
  }

  public InstanceKey getInstanceKeyForMultiNewArray(
      CGNode node, NewSiteReference allocation, int dim) {
    if (allocationPolicy()) {
      return siteBased.getInstanceKeyForMultiNewArray(node, allocation, dim);
    } else {
      return classBased.getInstanceKeyForMultiNewArray(node, allocation, dim);
    }
  }

  public <T> InstanceKey getInstanceKeyForConstant(TypeReference type, T S) {
    if (type == null) {
      throw new IllegalArgumentException("null type");
    }
    if (disambiguateConstants() || isReflectiveType(type)) {
      return new ConstantKey<T>(S, getClassHierarchy().lookupClass(type));
    } else {
      return classBased.getInstanceKeyForConstant(type, S);
    }
  }

  private boolean isReflectiveType(TypeReference type) {
    return type.equals(TypeReference.JavaLangReflectConstructor)
        || type.equals(TypeReference.JavaLangReflectMethod);
  }

  /*
   * @see com.ibm.wala.ipa.callgraph.propagation.InstanceKeyFactory#getInstanceKeyForPEI(com.ibm.wala.ipa.callgraph.CGNode,
   * com.ibm.wala.classLoader.ProgramCounter, com.ibm.wala.types.TypeReference)
   */
  public InstanceKey getInstanceKeyForPEI(CGNode node, ProgramCounter pei, TypeReference type) {
    return classBased.getInstanceKeyForPEI(node, pei, type);
  }

  public InstanceKey getInstanceKeyForClassObject(TypeReference type) {
    return classBased.getInstanceKeyForClassObject(type);
  }

  /** A class is "interesting" iff we distinguish instances of the class */
  public boolean isInteresting(IClass C) {
    if (!allocationPolicy()) {
      return false;
    } else {
      if (smushStrings() && isStringish(C)) {
        return false;
      } else if (smushThrowables() && (isThrowable(C) || isStackTraceElement(C))) {
        return false;
      } else if (smushPrimHolders() && allFieldsArePrimitive(C)) {
        return false;
      }
      return true;
    }
  }

  public static boolean isStringish(IClass C) {
    if (C == null) {
      throw new IllegalArgumentException("C is null");
    }
    return C.getReference().equals(TypeReference.JavaLangString)
        || C.getReference().equals(JavaLangStringBuffer)
        || C.getReference().equals(JavaLangStringBuilder)
        || C.getReference().equals(JavaLangAbstractStringBuilder);
  }

  public static boolean isThrowable(IClass c) {
    if (c == null) {
      throw new IllegalArgumentException("null c");
    }
    return c.getClassHierarchy()
        .isSubclassOf(c, c.getClassHierarchy().lookupClass(TypeReference.JavaLangThrowable));
  }

  public boolean isStackTraceElement(IClass c) {
    if (c == null) {
      throw new IllegalArgumentException("C is null");
    }
    return c.getReference().equals(TypeReference.JavaLangStackTraceElement);
  }

  private boolean allFieldsArePrimitive(IClass c) {
    if (c.isArrayClass()) {
      TypeReference t = c.getReference().getArrayElementType();
      return t.isPrimitiveType();
    } else {
      if (c.getReference().equals(TypeReference.JavaLangObject)) {
        return true;
      } else {
        for (Iterator<IField> it = c.getDeclaredInstanceFields().iterator(); it.hasNext(); ) {
          IField f = it.next();
          if (f.getReference().getFieldType().isReferenceType()) {
            return false;
          }
        }
        return allFieldsArePrimitive(c.getSuperclass());
      }
    }
  }

  protected IClassHierarchy getClassHierarchy() {
    return cha;
  }

  public ClassBasedInstanceKeys getClassBasedInstanceKeys() {
    return classBased;
  }
}
  private IMethod makeFunctionConstructor(
      IR callerIR, SSAAbstractInvokeInstruction callStmt, IClass cls, int nargs) {
    SymbolTable ST = callerIR.getSymbolTable();

    if (nargs == 0) {
      return makeFunctionConstructor(cls, cls);
    } else if (nargs == 1) {
      if (ST.isStringConstant(callStmt.getUse(1))) {
        TypeReference ref =
            TypeReference.findOrCreate(
                JavaScriptTypes.jsLoader,
                TypeName.string2TypeName((String) ST.getStringValue(callStmt.getUse(1))));

        if (DEBUG) {
          System.err.println(
              ("ctor type name is " + (String) ST.getStringValue(callStmt.getUse(1))));
        }

        IClass cls2 = cha.lookupClass(ref);
        if (cls2 != null) {
          return makeFunctionConstructor(cls, cls2);
        }
      }

      return makeFunctionConstructor(cls, cls);
    } else {
      assert nargs > 1;
      JavaScriptLoader cl = (JavaScriptLoader) cha.getLoader(JavaScriptTypes.jsLoader);

      for (int i = 1; i < callStmt.getNumberOfUses(); i++)
        if (!ST.isStringConstant(callStmt.getUse(i))) return makeFunctionConstructor(cls, cls);

      StringBuffer fun = new StringBuffer("function _fromctor (");
      for (int j = 1; j < callStmt.getNumberOfUses() - 1; j++) {
        if (j != 1) fun.append(",");
        fun.append(ST.getStringValue(callStmt.getUse(j)));
      }

      fun.append(") {");
      fun.append(ST.getStringValue(callStmt.getUse(callStmt.getNumberOfUses() - 1)));
      fun.append("}");

      try {
        String fileName = "ctor$" + ++ctorCount;
        File f = new File(System.getProperty("java.io.tmpdir") + File.separator + fileName);
        FileWriter FO = new FileWriter(f);
        FO.write(fun.toString());
        FO.close();

        Set<String> fnNames =
            JSCallGraphUtil.loadAdditionalFile(cha, cl, fileName, f.toURI().toURL());
        IClass fcls = null;
        for (String nm : fnNames) {
          if (nm.endsWith("_fromctor")) {
            fcls = cl.lookupClass(nm, cha);
          }
        }

        assert fcls != null : "cannot find class for " + fileName + " in " + f;

        f.delete();

        if (DEBUG) System.err.println(("looking for ctor " + ctorCount + " and got " + fcls));

        if (fcls != null) return makeFunctionConstructor(cls, fcls);

      } catch (IOException e) {

      }

      return makeFunctionConstructor(cls, cls);
    }
  }
 /**
  * @param m
  * @return true iff we can treat m as a no-op method
  */
 protected boolean canIgnore(MemberReference m) {
   TypeReference T = m.getDeclaringClass();
   TypeName n = T.getName();
   Atom p = n.getPackage();
   return (ignoredPackages.contains(p));
 }
Example #27
0
  private static List<Pair<CGNode, SSACheckCastInstruction>> findFailingCasts(
      CallGraph cg, DemandRefinementPointsTo dmp) {
    final IClassHierarchy cha = dmp.getClassHierarchy();
    List<Pair<CGNode, SSACheckCastInstruction>> failing =
        new ArrayList<Pair<CGNode, SSACheckCastInstruction>>();

    int numSafe = 0, numMightFail = 0;
    outer:
    for (Iterator<? extends CGNode> nodeIter = cg.iterator(); nodeIter.hasNext(); ) {
      CGNode node = nodeIter.next();
      TypeReference declaringClass = node.getMethod().getReference().getDeclaringClass();
      // skip library classes
      if (declaringClass.getClassLoader().equals(ClassLoaderReference.Primordial)) {
        continue;
      }
      IR ir = node.getIR();
      if (ir == null) continue;
      SSAInstruction[] instrs = ir.getInstructions();
      for (int i = 0; i < instrs.length; i++) {
        if (numSafe + numMightFail > MAX_CASTS) break outer;
        SSAInstruction instruction = instrs[i];
        if (instruction instanceof SSACheckCastInstruction) {
          SSACheckCastInstruction castInstr = (SSACheckCastInstruction) instruction;
          final TypeReference[] declaredResultTypes = castInstr.getDeclaredResultTypes();

          boolean primOnly = true;
          for (TypeReference t : declaredResultTypes) {
            if (!t.isPrimitiveType()) {
              primOnly = false;
            }
          }
          if (primOnly) {
            continue;
          }

          System.err.println("CHECKING " + castInstr + " in " + node.getMethod());
          PointerKey castedPk = heapModel.getPointerKeyForLocal(node, castInstr.getUse(0));
          Predicate<InstanceKey> castPred =
              new Predicate<InstanceKey>() {

                @Override
                public boolean test(InstanceKey ik) {
                  TypeReference ikTypeRef = ik.getConcreteType().getReference();
                  for (TypeReference t : declaredResultTypes) {
                    if (cha.isAssignableFrom(cha.lookupClass(t), cha.lookupClass(ikTypeRef))) {
                      return true;
                    }
                  }
                  return false;
                }
              };
          long startTime = System.currentTimeMillis();
          Pair<PointsToResult, Collection<InstanceKey>> queryResult =
              dmp.getPointsTo(castedPk, castPred);
          long runningTime = System.currentTimeMillis() - startTime;
          System.err.println("running time: " + runningTime + "ms");
          final FieldRefinePolicy fieldRefinePolicy =
              dmp.getRefinementPolicy().getFieldRefinePolicy();
          switch (queryResult.fst) {
            case SUCCESS:
              System.err.println("SAFE: " + castInstr + " in " + node.getMethod());
              if (fieldRefinePolicy instanceof ManualFieldPolicy) {
                ManualFieldPolicy hackedFieldPolicy = (ManualFieldPolicy) fieldRefinePolicy;
                System.err.println(hackedFieldPolicy.getHistory());
              }
              System.err.println("TRAVERSED " + dmp.getNumNodesTraversed() + " nodes");
              numSafe++;
              break;
            case NOMOREREFINE:
              if (queryResult.snd != null) {
                System.err.println(
                    "MIGHT FAIL: no more refinement possible for "
                        + castInstr
                        + " in "
                        + node.getMethod());
              } else {
                System.err.println(
                    "MIGHT FAIL: exceeded budget for " + castInstr + " in " + node.getMethod());
              }
              failing.add(Pair.make(node, castInstr));
              numMightFail++;
              break;
            case BUDGETEXCEEDED:
              System.err.println(
                  "MIGHT FAIL: exceeded budget for " + castInstr + " in " + node.getMethod());
              failing.add(Pair.make(node, castInstr));
              numMightFail++;
              break;
            default:
              Assertions.UNREACHABLE();
          }
        }
      }
      // break outer;
    }
    System.err.println("TOTAL SAFE: " + numSafe);
    System.err.println("TOTAL MIGHT FAIL: " + numMightFail);
    return failing;
  }
Example #28
0
 private boolean createOutputParamFor(final TypeReference type) {
   return !type.isPrimitiveType() && !sdg.isImmutableNoOutParam(type);
 }