Beispiel #1
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);
  }
Beispiel #2
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);
 }
Beispiel #3
0
  private void computeSuperclass() {
    superclassComputed = true;

    if (superName == null) {
      if (!getReference().equals(loader.getLanguage().getRootType())) {
        superClass = loader.lookupClass(loader.getLanguage().getRootType().getName());
      }
      return;
    }

    superClass = loader.lookupClass(TypeName.findOrCreate(superName));
  }
Beispiel #4
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)));
  }
Beispiel #5
0
 /**
  * @param interfaces a set of class names
  * @return Set of all IClasses that can be loaded corresponding to the class names in the
  *     interfaces array; raise warnings if classes can not be loaded
  */
 private Collection<IClass> array2IClassSet(ImmutableByteArray[] interfaces) {
   ArrayList<IClass> result = new ArrayList<IClass>(interfaces.length);
   for (int i = 0; i < interfaces.length; i++) {
     ImmutableByteArray name = interfaces[i];
     IClass klass = null;
     klass = loader.lookupClass(TypeName.findOrCreate(name));
     if (klass == null) {
       Warnings.add(ClassNotFoundWarning.create(name));
     } else {
       result.add(klass);
     }
   }
   return result;
 }
 /**
  * @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));
 }
  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);
    }
  }
Beispiel #8
0
public class LoadFileTargetSelector implements MethodTargetSelector {

  private final MethodTargetSelector base;

  private final JSSSAPropagationCallGraphBuilder builder;

  private final TypeReference loadFileRef =
      TypeReference.findOrCreate(
          JavaScriptTypes.jsLoader, TypeName.string2TypeName("Lprologue.js/loadFile"));

  private final MethodReference loadFileFunRef = AstMethodReference.fnReference(loadFileRef);

  private final HashSet<URL> loadedFiles = HashSetFactory.make();

  @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;
  }

  public LoadFileTargetSelector(
      MethodTargetSelector base, JSSSAPropagationCallGraphBuilder builder) {
    super();
    this.base = base;
    this.builder = builder;
  }
}
 private String getClassName(IClass clazz) {
   TypeName typeName = clazz.getName();
   return typeName.getPackage().toString().replaceAll("/", ".") + "." + typeName.getClassName();
 }
/**
 * 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;
  }
}