@Override
  public String toString() {
    StringBuilder s = new StringBuilder();
    String n = String.format("%n");

    s.append("Equivalent methods:" + n);
    for (Method bzm : manifest.getBaseMethods()) {
      s.append("  " + bzm.getName() + " -> { ");
      for (Method zm : ELM.get(bzm))
        s.append(zm.getReturnType() + ":" + zm.getName() + " "); // TODO fix this info
      s.append("}" + n);
    }

    s.append("Equivalent types:" + n);
    for (JavaClass bzt : manifest.getBaseTypes()) {
      s.append("  " + bzt.getClassName() + " -> { ");
      for (JavaClass zt : ET.get(bzt)) s.append(zt.getClassName() + " ");
      s.append("}" + n);
    }

    s.append("Method costs:" + n);
    for (Method zm : CLM.keySet())
      s.append("  " + zm.getName() + " -> " + CLM.get(zm).getName() + n);

    s.append("Transformation costs:" + n);
    for (Method zs : CLS.keySet())
      s.append("  " + zs.getName() + " -> " + CLS.get(zs).getName() + n);

    return s.toString();
  }
  @Override
  public void visit(JavaClass obj) {
    compute();
    ConstantPool cp = obj.getConstantPool();
    Constant[] constants = cp.getConstantPool();
    checkConstant:
    for (int i = 0; i < constants.length; i++) {
      Constant co = constants[i];
      if (co instanceof ConstantDouble || co instanceof ConstantLong) i++;
      if (co instanceof ConstantClass) {
        String ref = getClassName(obj, i);
        if ((ref.startsWith("java") || ref.startsWith("org.w3c.dom")) && !defined.contains(ref))
          bugReporter.reportBug(
              new BugInstance(this, "VR_UNRESOLVABLE_REFERENCE", NORMAL_PRIORITY)
                  .addClass(obj)
                  .addString(ref));

      } else if (co instanceof ConstantFieldref) {
        // do nothing until we handle static fields defined in interfaces
      } else if (co instanceof ConstantCP) {
        ConstantCP co2 = (ConstantCP) co;
        String className = getClassName(obj, co2.getClassIndex());

        // System.out.println("checking " + ref);
        if (className.equals(obj.getClassName()) || !defined.contains(className)) {
          // System.out.println("Skipping check of " + ref);
          continue checkConstant;
        }
        ConstantNameAndType nt = (ConstantNameAndType) cp.getConstant(co2.getNameAndTypeIndex());
        String name =
            ((ConstantUtf8) obj.getConstantPool().getConstant(nt.getNameIndex(), CONSTANT_Utf8))
                .getBytes();
        String signature =
            ((ConstantUtf8)
                    obj.getConstantPool().getConstant(nt.getSignatureIndex(), CONSTANT_Utf8))
                .getBytes();

        try {
          JavaClass target = Repository.lookupClass(className);
          if (!find(target, name, signature))
            bugReporter.reportBug(
                new BugInstance(this, "VR_UNRESOLVABLE_REFERENCE", NORMAL_PRIORITY)
                    .addClass(obj)
                    .addString(getMemberName(target.getClassName(), name, signature)));

        } catch (ClassNotFoundException e) {
          bugReporter.reportMissingClass(e);
        }
      }
    }
  }
  @Override
  public void sawOpcode(int seen) {
    if (seen == PUTFIELD) {
      XField xField = getXFieldOperand();
      if (xField != null && xField.getClassDescriptor().equals(getClassDescriptor())) {
        Item first = stack.getStackItem(0);
        boolean isPutOfDefaultValue = first.isNull(); // huh?? || first.isInitialParameter();
        if (!isPutOfDefaultValue && first.getConstant() != null) {
          Object constant = first.getConstant();
          if (constant instanceof Number && ((Number) constant).intValue() == 0
              || constant.equals(Boolean.FALSE)) isPutOfDefaultValue = true;
        }

        if (isPutOfDefaultValue) {
          if (getMethodName().equals("<init>"))
            transientFieldsSetToDefaultValueInConstructor.add(xField);
        } else {
          String nameOfField = getNameConstantOperand();

          if (transientFieldsUpdates.containsKey(xField)) {
            if (getMethodName().equals("<init>")) transientFieldsSetInConstructor.add(xField);
            else transientFieldsUpdates.put(xField, transientFieldsUpdates.get(xField) + 1);
          } else if (fieldsThatMightBeAProblem.containsKey(nameOfField)) {
            try {

              JavaClass classStored = first.getJavaClass();
              if (classStored == null) {
                return;
              }
              double isSerializable = DeepSubtypeAnalysis.isDeepSerializable(classStored);
              if (isSerializable <= 0.2) {
                XField f = fieldsThatMightBeAProblem.get(nameOfField);

                String sig = f.getSignature();
                // System.out.println("Field signature: " + sig);
                // System.out.println("Class stored: " +
                // classStored.getClassName());
                String genSig = "L" + classStored.getClassName().replace('.', '/') + ";";
                if (!sig.equals(genSig)) {
                  double bias = 0.0;
                  if (!getMethodName().equals("<init>")) bias = 1.0;
                  int priority = computePriority(isSerializable, bias);

                  fieldWarningList.add(
                      new BugInstance(this, "SE_BAD_FIELD_STORE", priority)
                          .addClass(getThisClass().getClassName())
                          .addField(f)
                          .addType(genSig)
                          .describe("TYPE_FOUND")
                          .addSourceLine(this));
                }
              }
            } catch (Exception e) {
              // ignore it
            }
          }
        }
      }
    }
  }
  @Override
  public ArtifactBuilder buildArtifacts(
      BaseArtifactType primaryArtifact, ArtifactContent artifactContent) throws IOException {
    super.buildArtifacts(primaryArtifact, artifactContent);

    ClassParser parser = new ClassParser(getContentStream(), primaryArtifact.getName());
    JavaClass javaClass = parser.parse();
    if (javaClass.isInterface()) {
      ((ExtendedDocument) primaryArtifact).setExtendedType(JavaModel.TYPE_JAVA_INTERFACE);
    } else if (javaClass.isClass()) {
      ((ExtendedDocument) primaryArtifact).setExtendedType(JavaModel.TYPE_JAVA_CLASS);
    } else if (javaClass.isEnum()) {
      ((ExtendedDocument) primaryArtifact).setExtendedType(JavaModel.TYPE_JAVA_ENUM);
    }
    String packageName = javaClass.getPackageName();
    String className = javaClass.getClassName();
    primaryArtifact.setName(className);
    String shortName = className;
    if (className.lastIndexOf('.') > 0) {
      shortName = className.substring(className.lastIndexOf('.') + 1);
    }
    SrampModelUtils.setCustomProperty(primaryArtifact, JavaModel.PROP_PACKAGE_NAME, packageName);
    SrampModelUtils.setCustomProperty(primaryArtifact, JavaModel.PROP_CLASS_NAME, shortName);

    return this;
  }
Exemple #5
0
  /**
   * Write contents of the given JavaClass into HTML files.
   *
   * @param java_class The class to write
   * @param dir The directory to put the files in
   */
  public Class2HTML(JavaClass java_class, String dir) throws IOException {
    Method[] methods = java_class.getMethods();

    this.java_class = java_class;
    this.dir = dir;
    class_name = java_class.getClassName(); // Remember full name
    constant_pool = java_class.getConstantPool();

    // Get package name by tacking off everything after the last `.'
    int index = class_name.lastIndexOf('.');
    if (index > -1) class_package = class_name.substring(0, index);
    else class_package = ""; // default package

    ConstantHTML constant_html =
        new ConstantHTML(dir, class_name, class_package, methods, constant_pool);

    /* Attributes can't be written in one step, so we just open a file
     * which will be written consequently.
     */
    AttributeHTML attribute_html = new AttributeHTML(dir, class_name, constant_pool, constant_html);

    // MethodHTML method_html = new MethodHTML(dir, class_name, methods, java_class.getFields(),
    //				    constant_html, attribute_html);
    // Write main file (with frames, yuk)
    writeMainHTML(attribute_html);
    new CodeHTML(dir, class_name, methods, constant_pool, constant_html);
    attribute_html.close();
  }
Exemple #6
0
  public static void main(String[] argv) throws Exception {
    JavaClass clazz = null;

    if ((clazz = Repository.lookupClass(argv[0])) == null) {
      clazz = new ClassParser(argv[0]).parse(); // May throw IOException
    }

    ClassGen cg = new ClassGen(clazz);

    Method[] methods = clazz.getMethods();

    for (int i = 0; i < methods.length; i++) {
      MethodGen mg = new MethodGen(methods[i], cg.getClassName(), cg.getConstantPool());
      cg.replaceMethod(methods[i], mg.getMethod());
    }

    Field[] fields = clazz.getFields();

    for (int i = 0; i < fields.length; i++) {
      FieldGen fg = new FieldGen(fields[i], cg.getConstantPool());
      cg.replaceField(fields[i], fg.getField());
    }

    cg.getJavaClass().dump(clazz.getClassName() + ".clazz");
  }
  /**
   * Dumps the contents of the specified class to the specified directory. The file is named
   * dump_dir/[class].bcel. It contains a synopsis of the fields and methods followed by the jvm
   * code for each method.
   *
   * @param jc javaclass to dump
   * @param dump_dir directory in which to write the file
   */
  public static void dump(JavaClass jc, File dump_dir) {

    try {
      dump_dir.mkdir();
      File path = new File(dump_dir, jc.getClassName() + ".bcel");
      PrintStream p = new PrintStream(path);

      // Print the class, super class and interfaces
      p.printf("class %s extends %s\n", jc.getClassName(), jc.getSuperclassName());
      String[] inames = jc.getInterfaceNames();
      if ((inames != null) && (inames.length > 0)) {
        p.printf("   ");
        for (String iname : inames) p.printf("implements %s ", iname);
        p.printf("\n");
      }

      // Print each field
      p.printf("\nFields\n");
      for (Field f : jc.getFields()) p.printf("  %s\n", f);

      // Print the signature of each method
      p.printf("\nMethods\n");
      for (Method m : jc.getMethods()) p.printf("  %s\n", m);

      // If this is not an interface, print the code for each method
      if (!jc.isInterface()) {
        for (Method m : jc.getMethods()) {
          p.printf("\nMethod %s\n", m);
          Code code = m.getCode();
          if (code != null) p.printf("  %s\n", code.toString().replace("\n", "\n  "));
        }
      }

      // Print the details of the constant pool.
      p.printf("Constant Pool:\n");
      ConstantPool cp = jc.getConstantPool();
      Constant[] constants = cp.getConstantPool();
      for (int ii = 0; ii < constants.length; ii++) {
        p.printf("  %d %s\n", ii, constants[ii]);
      }

      p.close();

    } catch (Exception e) {
      throw new Error("Unexpected error dumping javaclass", e);
    }
  }
Exemple #8
0
 /**
  * Construct a MethodDescriptor from JavaClass and method.
  *
  * @param jclass a JavaClass
  * @param method a Method belonging to the JavaClass
  * @return a MethodDescriptor identifying the method
  */
 public static MethodDescriptor getMethodDescriptor(JavaClass jclass, Method method) {
   return DescriptorFactory.instance()
       .getMethodDescriptor(
           jclass.getClassName().replace('.', '/'),
           method.getName(),
           method.getSignature(),
           method.isStatic());
 }
 private boolean find(JavaClass target, String name, String signature)
     throws ClassNotFoundException {
   if (target == null) return false;
   String ref = getMemberName(target.getClassName(), name, signature);
   if (defined.contains(ref)) return true;
   if (find(target.getSuperClass(), name, signature)) return true;
   for (JavaClass i : target.getInterfaces()) if (find(i, name, signature)) return true;
   return false;
 }
Exemple #10
0
  /**
   * Constructor is only used by following two factory methods: getTemplate for the dispatch of the
   * creation with newClassInfo
   *
   * @param clazz
   * @param ai
   */
  private JopClassInfo(JavaClass clazz, OldAppInfo ai) {
    super(clazz, ai);
    methodsAddress = 0;
    cpoolAddress = 0;
    instSize = 0;
    instGCinfo = 0;
    cpoolUsed = new LinkedList<Integer>();

    // the template class info is created with a null pointer
    if (clazz != null) {
      if (clazz.getClassName().equals(JOPizer.stringClass)) {
        StringInfo.cli = this;
      }
      if (clazz.getClassName().equals(JOPizer.objectClass)) {
        nrObjMethods = clazz.getMethods().length;
      }
    }
  }
Exemple #11
0
    public void visitJavaClass(JavaClass clazz) {

      super.visitJavaClass(clazz);
      JopClassInfo cli = (JopClassInfo) this.cli;

      cpool = clazz.getConstantPool();

      if (clazz.isInterface()) {
        cli.interfaceID = ++cli.interfaceCnt;
        cli.interfaceList.add(cli.interfaceID - 1, clazz.getClassName());
      }
    }
  public void addAllDefinitions(JavaClass obj) {
    String className2 = obj.getClassName();

    defined.add(className2);
    for (Method m : obj.getMethods())
      if (!m.isPrivate()) {
        String name = getMemberName(obj, className2, m.getNameIndex(), m.getSignatureIndex());
        defined.add(name);
      }
    for (Field f : obj.getFields())
      if (!f.isPrivate()) {
        String name = getMemberName(obj, className2, f.getNameIndex(), f.getSignatureIndex());
        defined.add(name);
      }
  }
  public void visitClassContext(ClassContext classContext) {
    JavaClass javaClass = classContext.getJavaClass();
    Method[] methodList = javaClass.getMethods();

    for (Method method : methodList) {
      if (method.getCode() == null) continue;

      try {
        analyzeMethod(classContext, method);
      } catch (MethodUnprofitableException e) {
        assert true; // move along; nothing to see
      } catch (CFGBuilderException e) {
        String msg =
            "Detector "
                + this.getClass().getName()
                + " caught exception while analyzing "
                + javaClass.getClassName()
                + "."
                + method.getName()
                + " : "
                + method.getSignature();
        bugReporter.logError(msg, e);
      } catch (DataflowAnalysisException e) {
        String msg =
            "Detector "
                + this.getClass().getName()
                + " caught exception while analyzing "
                + javaClass.getClassName()
                + "."
                + method.getName()
                + " : "
                + method.getSignature();
        bugReporter.logError(msg, e);
      }
    }
  }
  /**
   * looks to see if this class (or some class in its hierarchy (besides Object) has implemented the
   * specified method.
   *
   * @param cls the class to look in
   * @param methodName the method name to look for
   * @param methodSig the method signature to look for
   * @return when toString is found
   * @throws ClassNotFoundException if a super class can't be found
   */
  private static boolean hasMethodInHierarchy(JavaClass cls, String methodName, String methodSig)
      throws ClassNotFoundException {
    MethodInfo mi = null;

    do {
      String clsName = cls.getClassName();
      if (Values.DOTTED_JAVA_LANG_OBJECT.equals(clsName)) {
        return false;
      }

      mi =
          Statistics.getStatistics()
              .getMethodStatistics(clsName.replace('.', '/'), methodName, methodSig);
      cls = cls.getSuperClass();
    } while (mi.getNumBytes() == 0);

    return true;
  }
Exemple #15
0
  /**
   * Get the ClassContext for a class.
   *
   * @param javaClass the class
   * @return the ClassContext for that class
   */
  public ClassContext getClassContext(JavaClass javaClass) {
    // This is a bit silly since we're doing an unnecessary
    // ClassDescriptor->JavaClass lookup.
    // However, we can be assured that it will succeed.

    ClassDescriptor classDescriptor =
        DescriptorFactory.instance()
            .getClassDescriptor(ClassName.toSlashedClassName(javaClass.getClassName()));

    try {
      return Global.getAnalysisCache().getClassAnalysis(ClassContext.class, classDescriptor);
    } catch (CheckedAnalysisException e) {
      IllegalStateException ise =
          new IllegalStateException("Could not get ClassContext for JavaClass");
      ise.initCause(e);
      throw ise;
    }
  }
 public static @CheckForNull JavaClassAndMethod findMethod(
     JavaClass javaClass, String methodName, String methodSig, JavaClassAndMethodChooser chooser) {
   if (DEBUG_METHOD_LOOKUP) {
     System.out.println("Check " + javaClass.getClassName());
   }
   Method[] methodList = javaClass.getMethods();
   for (Method method : methodList)
     if (method.getName().equals(methodName) && method.getSignature().equals(methodSig)) {
       JavaClassAndMethod m = new JavaClassAndMethod(javaClass, method);
       if (chooser.choose(m)) {
         if (DEBUG_METHOD_LOOKUP) {
           System.out.println("\t==> FOUND: " + method);
         }
         return m;
       }
     }
   if (DEBUG_METHOD_LOOKUP) {
     System.out.println("\t==> NOT FOUND");
   }
   return null;
 }
  /**
   * Find a method in given class.
   *
   * @param javaClass the class
   * @param methodName the name of the method
   * @param methodSig the signature of the method
   * @return the JavaClassAndMethod, or null if no such method exists in the class
   */
  @Deprecated
  public static @CheckForNull JavaClassAndMethod findConcreteMethod(
      JavaClass javaClass, String methodName, String methodSig) {

    if (DEBUG_METHOD_LOOKUP) {
      System.out.println("Check " + javaClass.getClassName());
    }
    Method[] methodList = javaClass.getMethods();
    for (Method method : methodList)
      if (method.getName().equals(methodName)
          && method.getSignature().equals(methodSig)
          && accessFlagsAreConcrete(method.getAccessFlags())) {
        JavaClassAndMethod m = new JavaClassAndMethod(javaClass, method);

        return m;
      }
    if (DEBUG_METHOD_LOOKUP) {
      System.out.println("\t==> NOT FOUND");
    }
    return null;
  }
 @Override
 public void visit(Code obj) {
   if (!directChildOfTestCase
       && (getMethodName().equals("setUp") || getMethodName().equals("tearDown"))
       && !getMethod().isPrivate()
       && getMethodSig().equals("()V")) {
     sawSuperCall = false;
     super.visit(obj);
     if (sawSuperCall) {
       return;
     }
     JavaClass we =
         Lookup.findSuperImplementor(getThisClass(), getMethodName(), "()V", bugReporter);
     if (we != null && !we.getClassName().equals("junit.framework.TestCase")) {
       // OK, got a bug
       int offset = 0;
       if (getMethodName().equals("tearDown")) {
         offset = obj.getCode().length - 1;
       }
       Method superMethod = Lookup.findImplementation(we, getMethodName(), "()V");
       Code superCode = superMethod.getCode();
       if (superCode != null && superCode.getCode().length > 3) {
         bugReporter.reportBug(
             new BugInstance(
                     this,
                     getMethodName().equals("setUp")
                         ? "IJU_SETUP_NO_SUPER"
                         : "IJU_TEARDOWN_NO_SUPER",
                     NORMAL_PRIORITY)
                 .addClassAndMethod(this)
                 .addMethod(we, superMethod)
                 .describe(MethodAnnotation.METHOD_OVERRIDDEN)
                 .addSourceLine(this, offset));
       }
     }
   }
 }
 public void removeClass(JavaClass clazz) {
   ClassInfo cls = AppInfo.getSingleton().getClassInfo(clazz.getClassName());
   if (cls != null) {
     AppInfo.getSingleton().removeClass(cls, true, true);
   }
 }
  /**
   * Pass 3b implements the data flow analysis as described in the Java Virtual Machine
   * Specification, Second Edition. Later versions will use LocalVariablesInfo objects to verify if
   * the verifier-inferred types and the class file's debug information (LocalVariables attributes)
   * match [TODO].
   *
   * @see org.apache.bcel.verifier.statics.LocalVariablesInfo
   * @see org.apache.bcel.verifier.statics.Pass2Verifier#getLocalVariablesInfo(int)
   */
  @Override
  public VerificationResult do_verify() {
    if (!myOwner.doPass3a(method_no).equals(VerificationResult.VR_OK)) {
      return VerificationResult.VR_NOTYET;
    }

    // Pass 3a ran before, so it's safe to assume the JavaClass object is
    // in the BCEL repository.
    JavaClass jc;
    try {
      jc = Repository.lookupClass(myOwner.getClassName());
    } catch (ClassNotFoundException e) {
      // FIXME: maybe not the best way to handle this
      throw new AssertionViolatedException("Missing class: " + e, e);
    }

    ConstantPoolGen constantPoolGen = new ConstantPoolGen(jc.getConstantPool());
    // Init Visitors
    InstConstraintVisitor icv = new InstConstraintVisitor();
    icv.setConstantPoolGen(constantPoolGen);

    ExecutionVisitor ev = new ExecutionVisitor();
    ev.setConstantPoolGen(constantPoolGen);

    Method[] methods = jc.getMethods(); // Method no "method_no" exists, we ran Pass3a before on it!

    try {

      MethodGen mg = new MethodGen(methods[method_no], myOwner.getClassName(), constantPoolGen);

      icv.setMethodGen(mg);

      ////////////// DFA BEGINS HERE ////////////////
      if (!(mg.isAbstract() || mg.isNative())) { // IF mg HAS CODE (See pass 2)

        ControlFlowGraph cfg = new ControlFlowGraph(mg);

        // Build the initial frame situation for this method.
        Frame f = new Frame(mg.getMaxLocals(), mg.getMaxStack());
        if (!mg.isStatic()) {
          if (mg.getName().equals(Constants.CONSTRUCTOR_NAME)) {
            Frame._this = new UninitializedObjectType(ObjectType.getInstance(jc.getClassName()));
            f.getLocals().set(0, Frame._this);
          } else {
            Frame._this = null;
            f.getLocals().set(0, ObjectType.getInstance(jc.getClassName()));
          }
        }
        Type[] argtypes = mg.getArgumentTypes();
        int twoslotoffset = 0;
        for (int j = 0; j < argtypes.length; j++) {
          if (argtypes[j] == Type.SHORT
              || argtypes[j] == Type.BYTE
              || argtypes[j] == Type.CHAR
              || argtypes[j] == Type.BOOLEAN) {
            argtypes[j] = Type.INT;
          }
          f.getLocals().set(twoslotoffset + j + (mg.isStatic() ? 0 : 1), argtypes[j]);
          if (argtypes[j].getSize() == 2) {
            twoslotoffset++;
            f.getLocals().set(twoslotoffset + j + (mg.isStatic() ? 0 : 1), Type.UNKNOWN);
          }
        }
        circulationPump(mg, cfg, cfg.contextOf(mg.getInstructionList().getStart()), f, icv, ev);
      }
    } catch (VerifierConstraintViolatedException ce) {
      ce.extendMessage("Constraint violated in method '" + methods[method_no] + "':\n", "");
      return new VerificationResult(VerificationResult.VERIFIED_REJECTED, ce.getMessage());
    } catch (RuntimeException re) {
      // These are internal errors

      StringWriter sw = new StringWriter();
      PrintWriter pw = new PrintWriter(sw);
      re.printStackTrace(pw);

      throw new AssertionViolatedException(
          "Some RuntimeException occured while verify()ing class '"
              + jc.getClassName()
              + "', method '"
              + methods[method_no]
              + "'. Original RuntimeException's stack trace:\n---\n"
              + sw
              + "---\n",
          re);
    }
    return VerificationResult.VR_OK;
  }
  /**
   * Adds all the constants found in the given class into the given ConstantSet, and returns it.
   *
   * @see #getConstants(String)
   */
  public static ConstantSet getConstants(String classname, ConstantSet result) {

    ClassParser cp;
    JavaClass jc;
    try {
      String classfileBase = classname.replace('.', '/');
      InputStream is = ClassPath.SYSTEM_CLASS_PATH.getInputStream(classfileBase, ".class");
      cp = new ClassParser(is, classname);
      jc = cp.parse();
    } catch (java.io.IOException e) {
      throw new Error("IOException while reading '" + classname + "': " + e.getMessage());
    }
    result.classname = jc.getClassName();

    // Get all of the constants from the pool
    ConstantPool constant_pool = jc.getConstantPool();
    for (Constant c : constant_pool.getConstantPool()) {
      // System.out.printf ("*Constant = %s%n", c);
      if (c == null
          || c instanceof ConstantClass
          || c instanceof ConstantFieldref
          || c instanceof ConstantInterfaceMethodref
          || c instanceof ConstantMethodref
          || c instanceof ConstantNameAndType
          || c instanceof ConstantUtf8) {
        continue;
      }
      if (c instanceof ConstantString) {
        result.strings.add((String) ((ConstantString) c).getConstantValue(constant_pool));
      } else if (c instanceof ConstantDouble) {
        result.doubles.add((Double) ((ConstantDouble) c).getConstantValue(constant_pool));
      } else if (c instanceof ConstantFloat) {
        result.floats.add((Float) ((ConstantFloat) c).getConstantValue(constant_pool));
      } else if (c instanceof ConstantInteger) {
        result.ints.add((Integer) ((ConstantInteger) c).getConstantValue(constant_pool));
      } else if (c instanceof ConstantLong) {
        result.longs.add((Long) ((ConstantLong) c).getConstantValue(constant_pool));
      } else {
        throw new RuntimeException("Unrecognized constant of type " + c.getClass() + ": " + c);
      }
    }

    ClassGen gen = new ClassGen(jc);
    ConstantPoolGen pool = gen.getConstantPool();

    // Process the code in each method looking for literals
    for (Method m : jc.getMethods()) {
      MethodGen mg = new MethodGen(m, jc.getClassName(), pool);
      InstructionList il = mg.getInstructionList();
      if (il == null) {
        // System.out.println("No instructions for " + mg);
      } else {
        for (Instruction inst : il.getInstructions()) {
          switch (inst.getOpcode()) {

              // Compare two objects, no literals
            case Constants.IF_ACMPEQ:
            case Constants.IF_ACMPNE:
              break;

              // These instructions compare the integer on the top of the stack
              // to zero.  There are no literals here (except 0)
            case Constants.IFEQ:
            case Constants.IFNE:
            case Constants.IFLT:
            case Constants.IFGE:
            case Constants.IFGT:
            case Constants.IFLE:
              {
                break;
              }

              // Instanceof pushes either 0 or 1 on the stack depending on whether
              // the object on top of stack is of the specified type.
              // If were interested in class literals, this would be interesting
            case Constants.INSTANCEOF:
              break;

              // Duplicates the item on the top of stack.  No literal.
            case Constants.DUP:
              {
                break;
              }

              // Duplicates the item on the top of the stack and inserts it 2
              // values down in the stack.  No literals
            case Constants.DUP_X1:
              {
                break;
              }

              // Duplicates either the top 2 category 1 values or a single
              // category 2 value and inserts it 2 or 3 values down on the
              // stack.
            case Constants.DUP2_X1:
              {
                break;
              }

              // Duplicate either one category 2 value or two category 1 values.
            case Constants.DUP2:
              {
                break;
              }

              // Dup the category 1 value on the top of the stack and insert it either
              // two or three values down on the stack.
            case Constants.DUP_X2:
              {
                break;
              }

            case Constants.DUP2_X2:
              {
                break;
              }

              // Pop instructions discard the top of the stack.
            case Constants.POP:
              {
                break;
              }

              // Pops either the top 2 category 1 values or a single category 2 value
              // from the top of the stack.
            case Constants.POP2:
              {
                break;
              }

              // Swaps the two category 1 types on the top of the stack.
            case Constants.SWAP:
              {
                break;
              }

              // Compares two integers on the stack
            case Constants.IF_ICMPEQ:
            case Constants.IF_ICMPGE:
            case Constants.IF_ICMPGT:
            case Constants.IF_ICMPLE:
            case Constants.IF_ICMPLT:
            case Constants.IF_ICMPNE:
              {
                break;
              }

              // Get the value of a field
            case Constants.GETFIELD:
              {
                break;
              }

              // stores the top of stack into a field
            case Constants.PUTFIELD:
              {
                break;
              }

              // Pushes the value of a static field on the stack
            case Constants.GETSTATIC:
              {
                break;
              }

              // Pops a value off of the stack into a static field
            case Constants.PUTSTATIC:
              {
                break;
              }

              // pushes a local onto the stack
            case Constants.DLOAD:
            case Constants.DLOAD_0:
            case Constants.DLOAD_1:
            case Constants.DLOAD_2:
            case Constants.DLOAD_3:
            case Constants.FLOAD:
            case Constants.FLOAD_0:
            case Constants.FLOAD_1:
            case Constants.FLOAD_2:
            case Constants.FLOAD_3:
            case Constants.ILOAD:
            case Constants.ILOAD_0:
            case Constants.ILOAD_1:
            case Constants.ILOAD_2:
            case Constants.ILOAD_3:
            case Constants.LLOAD:
            case Constants.LLOAD_0:
            case Constants.LLOAD_1:
            case Constants.LLOAD_2:
            case Constants.LLOAD_3:
              {
                break;
              }

              // Pops a value off of the stack into a local
            case Constants.DSTORE:
            case Constants.DSTORE_0:
            case Constants.DSTORE_1:
            case Constants.DSTORE_2:
            case Constants.DSTORE_3:
            case Constants.FSTORE:
            case Constants.FSTORE_0:
            case Constants.FSTORE_1:
            case Constants.FSTORE_2:
            case Constants.FSTORE_3:
            case Constants.ISTORE:
            case Constants.ISTORE_0:
            case Constants.ISTORE_1:
            case Constants.ISTORE_2:
            case Constants.ISTORE_3:
            case Constants.LSTORE:
            case Constants.LSTORE_0:
            case Constants.LSTORE_1:
            case Constants.LSTORE_2:
            case Constants.LSTORE_3:
              {
                break;
              }

              // Push a value from the runtime constant pool.  We'll get these
              // values when processing the constant pool itself
            case Constants.LDC:
            case Constants.LDC_W:
            case Constants.LDC2_W:
              {
                break;
              }

              // Push the length of an array on the stack
            case Constants.ARRAYLENGTH:
              {
                break;
              }

              // Push small constants (-1..5) on the stack.  These literals are
              // too common to bother mentioning
            case Constants.DCONST_0:
            case Constants.DCONST_1:
            case Constants.FCONST_0:
            case Constants.FCONST_1:
            case Constants.FCONST_2:
            case Constants.ICONST_0:
            case Constants.ICONST_1:
            case Constants.ICONST_2:
            case Constants.ICONST_3:
            case Constants.ICONST_4:
            case Constants.ICONST_5:
            case Constants.ICONST_M1:
            case Constants.LCONST_0:
            case Constants.LCONST_1:
              {
                break;
              }

            case Constants.BIPUSH:
            case Constants.SIPUSH:
              {
                ConstantPushInstruction cpi = (ConstantPushInstruction) inst;
                result.ints.add((Integer) cpi.getValue());
                break;
              }

              // Primitive Binary operators.
            case Constants.DADD:
            case Constants.DCMPG:
            case Constants.DCMPL:
            case Constants.DDIV:
            case Constants.DMUL:
            case Constants.DREM:
            case Constants.DSUB:
            case Constants.FADD:
            case Constants.FCMPG:
            case Constants.FCMPL:
            case Constants.FDIV:
            case Constants.FMUL:
            case Constants.FREM:
            case Constants.FSUB:
            case Constants.IADD:
            case Constants.IAND:
            case Constants.IDIV:
            case Constants.IMUL:
            case Constants.IOR:
            case Constants.IREM:
            case Constants.ISHL:
            case Constants.ISHR:
            case Constants.ISUB:
            case Constants.IUSHR:
            case Constants.IXOR:
            case Constants.LADD:
            case Constants.LAND:
            case Constants.LCMP:
            case Constants.LDIV:
            case Constants.LMUL:
            case Constants.LOR:
            case Constants.LREM:
            case Constants.LSHL:
            case Constants.LSHR:
            case Constants.LSUB:
            case Constants.LUSHR:
            case Constants.LXOR:
              break;

            case Constants.LOOKUPSWITCH:
            case Constants.TABLESWITCH:
              break;

            case Constants.ANEWARRAY:
            case Constants.NEWARRAY:
              {
                break;
              }

            case Constants.MULTIANEWARRAY:
              {
                break;
              }

              // push the value at an index in an array
            case Constants.AALOAD:
            case Constants.BALOAD:
            case Constants.CALOAD:
            case Constants.DALOAD:
            case Constants.FALOAD:
            case Constants.IALOAD:
            case Constants.LALOAD:
            case Constants.SALOAD:
              {
                break;
              }

              // Pop the top of stack into an array location
            case Constants.AASTORE:
            case Constants.BASTORE:
            case Constants.CASTORE:
            case Constants.DASTORE:
            case Constants.FASTORE:
            case Constants.IASTORE:
            case Constants.LASTORE:
            case Constants.SASTORE:
              break;

            case Constants.ARETURN:
            case Constants.DRETURN:
            case Constants.FRETURN:
            case Constants.IRETURN:
            case Constants.LRETURN:
            case Constants.RETURN:
              {
                break;
              }

              // subroutine calls.
            case Constants.INVOKESTATIC:
            case Constants.INVOKEVIRTUAL:
            case Constants.INVOKESPECIAL:
            case Constants.INVOKEINTERFACE:
              break;

              // Throws an exception.
            case Constants.ATHROW:
              break;

              // Opcodes that don't need any modifications.  Here for reference
            case Constants.ACONST_NULL:
            case Constants.ALOAD:
            case Constants.ALOAD_0:
            case Constants.ALOAD_1:
            case Constants.ALOAD_2:
            case Constants.ALOAD_3:
            case Constants.ASTORE:
            case Constants.ASTORE_0:
            case Constants.ASTORE_1:
            case Constants.ASTORE_2:
            case Constants.ASTORE_3:
            case Constants.CHECKCAST:
            case Constants.D2F: // double to float
            case Constants.D2I: // double to integer
            case Constants.D2L: // double to long
            case Constants.DNEG: // Negate double on top of stack
            case Constants.F2D: // float to double
            case Constants.F2I: // float to integer
            case Constants.F2L: // float to long
            case Constants.FNEG: // Negate float on top of stack
            case Constants.GOTO:
            case Constants.GOTO_W:
            case Constants.I2B: // integer to byte
            case Constants.I2C: // integer to char
            case Constants.I2D: // integer to double
            case Constants.I2F: // integer to float
            case Constants.I2L: // integer to long
            case Constants.I2S: // integer to short
            case Constants.IFNONNULL:
            case Constants.IFNULL:
            case Constants.IINC: // increment local variable by a constant
            case Constants.INEG: // negate integer on top of stack
            case Constants.JSR: // pushes return address on the stack,
            case Constants.JSR_W:
            case Constants.L2D: // long to double
            case Constants.L2F: // long to float
            case Constants.L2I: // long to int
            case Constants.LNEG: // negate long on top of stack
            case Constants.MONITORENTER:
            case Constants.MONITOREXIT:
            case Constants.NEW:
            case Constants.NOP:
            case Constants.RET: // this is the internal JSR return
              break;

              // Make sure we didn't miss anything
            default:
              throw new Error("instruction " + inst + " unsupported");
          }
        }
      }
    }
    return result;
  }
  /**
   * Given another class, return a transformed version of the class which replaces specified calls
   * with alternative static implementations
   */
  public byte[] transform(
      ClassLoader loader,
      String className,
      Class<?> classBeingRedefined,
      ProtectionDomain protectionDomain,
      byte[] classfileBuffer)
      throws IllegalClassFormatException {

    // debug = className.equals ("chicory/Test");

    String fullClassName = className.replace("/", ".");

    debug_transform.log("In Transform: class = %s%n", className);

    // Don't instrument boot classes.  We only want to instrument
    // user classes classpath.
    // Most boot classes have the null loader,
    // but some generated classes (such as those in sun.reflect) will
    // have a non-null loader.  Some of these have a null parent loader,
    // but some do not.  The check for the sun.reflect package is a hack
    // to catch all of these.  A more consistent mechanism to determine
    // boot classes would be preferrable.
    if (loader == null) {
      debug_transform.log("ignoring system class %s, class loader == null", fullClassName);
      return (null);
    } else if (loader.getParent() == null) {
      debug_transform.log("ignoring system class %s, parent loader == null\n", fullClassName);
      return (null);
    } else if (fullClassName.startsWith("sun.reflect")) {
      debug_transform.log("ignoring system class %s, in sun.reflect package", fullClassName);
      return (null);
    } else if (fullClassName.startsWith("com.sun")) {
      System.out.printf("Class from com.sun package %s with nonnull loaders\n", fullClassName);
    }

    // Don't intrument our code
    if (className.startsWith("randoop.")) {
      debug_transform.log("Not considering randoop class %s%n", fullClassName);
      return (null);
    }

    // Look for match with specified regular expressions for class
    method_map = null;
    debug_class = false;
    for (MethodMapInfo mmi : map_list) {
      if (mmi.class_regex.matcher(className).matches()) {
        if (false && className.startsWith("RandoopTest")) debug_class = true;
        if (debug_class)
          System.out.printf("Classname %s matches re %s%n", className, mmi.class_regex);
        method_map = mmi.map;
        break;
      }
    }
    if (method_map == null) return null;

    debug_transform.log(
        "transforming class %s, loader %s - %s%n", className, loader, loader.getParent());

    // Parse the bytes of the classfile, die on any errors
    JavaClass c = null;
    ClassParser parser = new ClassParser(new ByteArrayInputStream(classfileBuffer), className);
    try {
      c = parser.parse();
    } catch (Exception e) {
      throw new RuntimeException("Unexpected error", e);
    }

    try {
      // Get the class information
      ClassGen cg = new ClassGen(c);
      ifact = new InstructionFactory(cg);

      map_calls(cg, className, loader);

      JavaClass njc = cg.getJavaClass();
      if (debug) njc.dump("/tmp/ret/" + njc.getClassName() + ".class");

      if (true) {
        return (cg.getJavaClass().getBytes());
      } else {
        debug_transform.log("not including class %s (filtered out)", className);
        return null;
      }

    } catch (Throwable e) {
      out.format("Unexpected error %s in transform", e);
      e.printStackTrace();
      return (null);
    }
  }
Exemple #23
0
 @Override
 public String toString() {
   return clazz.getClassName() + "." + method.getName();
 }
  public static double isDeepSerializable(JavaClass x) throws ClassNotFoundException {
    if (storedException != null) throw storedException;

    if (x.getClassName().equals("java.lang.Object")) return 0.4;

    if (DEBUG) {
      System.out.println("checking " + x.getClassName());
    }

    double result = Analyze.deepInstanceOf(x, serializable);
    if (result >= 0.9) {
      if (DEBUG) {
        System.out.println("Direct high serializable result: " + result);
      }
      return result;
    }

    if (x.isFinal()) return result;

    double collectionResult = Analyze.deepInstanceOf(x, collection);
    double mapResult = Analyze.deepInstanceOf(x, map);

    if (x.isInterface() || x.isAbstract()) {
      result = Math.max(result, Math.max(mapResult, collectionResult) * 0.95);
      if (result >= 0.9) {
        return result;
      }
    }
    ClassDescriptor classDescriptor = DescriptorFactory.createClassDescriptor(x);

    Subtypes2 subtypes2 = AnalysisContext.currentAnalysisContext().getSubtypes2();

    Set<ClassDescriptor> directSubtypes = subtypes2.getDirectSubtypes(classDescriptor);
    directSubtypes.remove(classDescriptor);

    double confidence = 0.6;
    if (x.isAbstract() || x.isInterface()) {
      confidence = 0.8;
      result = Math.max(result, 0.4);
    } else if (directSubtypes.isEmpty()) confidence = 0.2;

    double confidence2 = (1 + confidence) / 2;
    result = Math.max(result, confidence2 * collectionResult);
    if (result >= 0.9) {
      if (DEBUG) {
        System.out.println("High collection result: " + result);
      }
      return result;
    }
    result = Math.max(result, confidence2 * mapResult);
    if (result >= 0.9) {
      if (DEBUG) {
        System.out.println("High map result: " + result);
      }
      return result;
    }
    result = Math.max(result, confidence2 * 0.5 * Analyze.deepInstanceOf(x, comparator));
    if (result >= 0.9) {
      if (DEBUG) {
        System.out.println("High comparator result: " + result);
      }
      return result;
    }

    for (ClassDescriptor subtype : directSubtypes) {
      JavaClass subJavaClass = Repository.lookupClass(subtype.getDottedClassName());
      result = Math.max(result, confidence * Analyze.deepInstanceOf(subJavaClass, serializable));

      // result = Math.max(result, confidence * isDeepSerializable(subJavaClass));
      if (result >= 0.9) {
        return result;
      }
    }

    if (DEBUG) {
      System.out.println("No high results; max: " + result);
    }
    return result;
  }
  @Override
  public void visitAfter(JavaClass obj) {
    if (isEnum) return;
    if (DEBUG) {
      System.out.println(getDottedClassName());
      System.out.println("  hasPublicVoidConstructor: " + hasPublicVoidConstructor);
      System.out.println("  superClassHasVoidConstructor: " + superClassHasVoidConstructor);
      System.out.println("  isExternalizable: " + isExternalizable);
      System.out.println("  isSerializable: " + isSerializable);
      System.out.println("  isAbstract: " + isAbstract);
      System.out.println("  superClassImplementsSerializable: " + superClassImplementsSerializable);
      System.out.println("  isGUIClass: " + isGUIClass);
      System.out.println("  isEjbImplClass: " + isEjbImplClass);
    }
    if (isSerializable
        && !sawReadObject
        && !sawReadResolve
        && seenTransientField
        && !superClassHasReadObject) {
      for (Map.Entry<XField, Integer> e : transientFieldsUpdates.entrySet()) {

        XField fieldX = e.getKey();
        int priority = NORMAL_PRIORITY;
        if (transientFieldsSetInConstructor.contains(e.getKey())) priority--;

        if (isGUIClass) priority++;
        if (isEjbImplClass) priority++;
        if (e.getValue() < 3) priority++;
        if (transientFieldsSetToDefaultValueInConstructor.contains(e.getKey())) priority++;
        if (obj.isAbstract()) {
          priority++;
          if (priority < Priorities.LOW_PRIORITY) priority = Priorities.LOW_PRIORITY;
        }

        try {
          double isSerializable = DeepSubtypeAnalysis.isDeepSerializable(fieldX.getSignature());
          if (isSerializable < 0.6) priority++;
        } catch (ClassNotFoundException e1) {
          // ignore it
        }

        bugReporter.reportBug(
            new BugInstance(this, "SE_TRANSIENT_FIELD_NOT_RESTORED", priority)
                .addClass(getThisClass())
                .addField(fieldX));
      }
    }
    if (isSerializable
        && !isExternalizable
        && !superClassHasVoidConstructor
        && !superClassImplementsSerializable) {
      int priority =
          implementsSerializableDirectly || seenTransientField
              ? HIGH_PRIORITY
              : (sawSerialVersionUID ? NORMAL_PRIORITY : LOW_PRIORITY);
      if (isGUIClass) priority++;
      if (isEjbImplClass) priority++;
      bugReporter.reportBug(
          new BugInstance(this, "SE_NO_SUITABLE_CONSTRUCTOR", priority)
              .addClass(getThisClass().getClassName()));
    }
    // Downgrade class-level warnings if it's a GUI or EJB-implementation class.
    int priority = (isGUIClass || isEjbImplClass) ? LOW_PRIORITY : NORMAL_PRIORITY;
    if (obj.getClassName().endsWith("_Stub")) priority++;

    if (isExternalizable && !hasPublicVoidConstructor && !isAbstract)
      bugReporter.reportBug(
          new BugInstance(
                  this,
                  "SE_NO_SUITABLE_CONSTRUCTOR_FOR_EXTERNALIZATION",
                  directlyImplementsExternalizable ? HIGH_PRIORITY : NORMAL_PRIORITY)
              .addClass(getThisClass().getClassName()));
    if (!foundSynthetic) priority++;
    if (seenTransientField) priority--;
    if (!isAnonymousInnerClass
        && !isExternalizable
        && !isGUIClass
        && !obj.isAbstract()
        && isSerializable
        && !isAbstract
        && !sawSerialVersionUID
        && !isEjbImplClass)
      bugReporter.reportBug(
          new BugInstance(this, "SE_NO_SERIALVERSIONID", priority).addClass(this));

    if (writeObjectIsSynchronized && !foundSynchronizedMethods)
      bugReporter.reportBug(
          new BugInstance(this, "WS_WRITEOBJECT_SYNC", LOW_PRIORITY).addClass(this));
  }
  @Override
  public void visit(JavaClass obj) {
    String superClassname = obj.getSuperclassName();
    // System.out.println("superclass of " + getClassName() + " is " + superClassname);
    isEnum = superClassname.equals("java.lang.Enum");
    if (isEnum) return;
    int flags = obj.getAccessFlags();
    isAbstract = (flags & ACC_ABSTRACT) != 0 || (flags & ACC_INTERFACE) != 0;
    isAnonymousInnerClass = anonymousInnerClassNamePattern.matcher(getClassName()).matches();
    innerClassHasOuterInstance = false;
    for (Field f : obj.getFields()) {
      if (f.getName().equals("this$0")) {
        innerClassHasOuterInstance = true;
        break;
      }
    }

    sawSerialVersionUID = false;
    isSerializable = implementsSerializableDirectly = false;
    isExternalizable = false;
    directlyImplementsExternalizable = false;
    isGUIClass = false;
    isEjbImplClass = false;
    seenTransientField = false;
    // boolean isEnum = obj.getSuperclassName().equals("java.lang.Enum");
    fieldsThatMightBeAProblem.clear();
    transientFieldsUpdates.clear();
    transientFieldsSetInConstructor.clear();
    transientFieldsSetToDefaultValueInConstructor.clear();
    // isRemote = false;

    // Does this class directly implement Serializable?
    String[] interface_names = obj.getInterfaceNames();
    for (String interface_name : interface_names) {
      if (interface_name.equals("java.io.Externalizable")) {
        directlyImplementsExternalizable = true;
        isExternalizable = true;
        if (DEBUG) {
          System.out.println("Directly implements Externalizable: " + getClassName());
        }
      } else if (interface_name.equals("java.io.Serializable")) {
        implementsSerializableDirectly = true;
        isSerializable = true;
        if (DEBUG) {
          System.out.println("Directly implements Serializable: " + getClassName());
        }
        break;
      }
    }

    // Does this class indirectly implement Serializable?
    if (!isSerializable) {
      if (Subtypes2.instanceOf(obj, "java.io.Externalizable")) {
        isExternalizable = true;
        if (DEBUG) {
          System.out.println("Indirectly implements Externalizable: " + getClassName());
        }
      }
      if (Subtypes2.instanceOf(obj, "java.io.Serializable")) {
        isSerializable = true;
        if (DEBUG) {
          System.out.println("Indirectly implements Serializable: " + getClassName());
        }
      }
    }

    hasPublicVoidConstructor = false;
    superClassHasVoidConstructor = true;
    superClassHasReadObject = false;
    superClassImplementsSerializable = isSerializable && !implementsSerializableDirectly;
    ClassDescriptor superclassDescriptor = getXClass().getSuperclassDescriptor();
    if (superclassDescriptor != null)
      try {
        XClass superXClass =
            Global.getAnalysisCache().getClassAnalysis(XClass.class, superclassDescriptor);
        if (superXClass != null) {
          superClassImplementsSerializable =
              AnalysisContext.currentAnalysisContext()
                  .getSubtypes2()
                  .isSubtype(
                      superXClass.getClassDescriptor(),
                      DescriptorFactory.createClassDescriptor(java.io.Serializable.class));
          superClassHasVoidConstructor = false;
          for (XMethod m : superXClass.getXMethods()) {
            if (m.getName().equals("<init>") && m.getSignature().equals("()V") && !m.isPrivate()) {
              superClassHasVoidConstructor = true;
            }
            if (m.getName().equals("readObject")
                && m.getSignature().equals("(Ljava/io/ObjectInputStream;)V")
                && m.isPrivate()) superClassHasReadObject = true;
          }
        }
      } catch (ClassNotFoundException e) {
        bugReporter.reportMissingClass(e);
      } catch (CheckedAnalysisException e) {
        bugReporter.logError("huh", e);
      }

    // Is this a GUI  or other class that is rarely serialized?

    isGUIClass = false;
    isEjbImplClass = false;
    if (true || !directlyImplementsExternalizable && !implementsSerializableDirectly) {
      isEjbImplClass = Subtypes2.instanceOf(obj, "javax.ejb.SessionBean");
      isGUIClass =
          (Subtypes2.instanceOf(obj, "java.lang.Throwable")
              || Subtypes2.instanceOf(obj, "java.awt.Component")
              || Subtypes2.instanceOf(obj, "java.awt.Component$AccessibleAWTComponent")
              || Subtypes2.instanceOf(obj, "java.awt.event.ActionListener")
              || Subtypes2.instanceOf(obj, "java.util.EventListener"));
      if (!isGUIClass) {
        JavaClass o = obj;
        while (o != null) {
          if (o.getClassName().startsWith("java.awt")
              || o.getClassName().startsWith("javax.swing")) {
            isGUIClass = true;
            break;
          }
          try {
            o = o.getSuperClass();
          } catch (ClassNotFoundException e) {
            break;
          }
        }
      }
    }

    foundSynthetic = false;
    foundSynchronizedMethods = false;
    writeObjectIsSynchronized = false;

    sawReadExternal = sawWriteExternal = sawReadObject = sawReadResolve = sawWriteObject = false;
    if (isSerializable) {
      for (Method m : obj.getMethods()) {

        if (m.getName().equals("readObject")
            && m.getSignature().equals("(Ljava/io/ObjectInputStream;)V")) sawReadObject = true;
        else if (m.getName().equals("readResolve") && m.getSignature().startsWith("()"))
          sawReadResolve = true;
        else if (m.getName().equals("readObjectNoData") && m.getSignature().equals("()V"))
          sawReadObject = true;
        else if (m.getName().equals("writeObject")
            && m.getSignature().equals("(Ljava/io/ObjectOutputStream;)V")) sawWriteObject = true;
      }
      for (Field f : obj.getFields()) {
        if (f.isTransient()) seenTransientField = true;
      }
    }
  }
 protected void generateClassContext(JavaClass jc) {
   mPoolGen = new ConstantPoolGen(jc.getConstantPool());
   mClassName = jc.getClassName();
   mClassMetrics = mMetricsContainer.getMetrics(mClassName);
 }
Exemple #28
0
 /**
  * Construct a ClassDescriptor from a JavaClass.
  *
  * @param jclass a JavaClass
  * @return a ClassDescriptor identifying that JavaClass
  */
 public static ClassDescriptor getClassDescriptor(JavaClass jclass) {
   return DescriptorFactory.instance()
       .getClassDescriptor(ClassName.toSlashedClassName(jclass.getClassName()));
 }
  /**
   * overrides the visitor to report on classes without toStrings that have fields
   *
   * @param classContext the context object of the currently parsed class
   */
  @Override
  public void visitClassContext(ClassContext classContext) {
    JavaClass cls = classContext.getJavaClass();

    if (cls.getPackageName().isEmpty()) {
      bugReporter.reportBug(
          new BugInstance(this, BugType.IMC_IMMATURE_CLASS_NO_PACKAGE.name(), LOW_PRIORITY)
              .addClass(cls));
    }

    if ((!cls.isAbstract())
        && (!cls.isEnum())
        && !cls.getClassName().contains("$")
        && !isTestClass(cls)) {

      try {
        boolean clsHasRuntimeAnnotation = classHasRuntimeVisibleAnnotation(cls);
        HEStatus heStatus = HEStatus.UNKNOWN;

        checkIDEGeneratedParmNames(cls);

        for (Field f : cls.getFields()) {
          if (!f.isStatic() && !f.isSynthetic()) {

            boolean fieldHasRuntimeAnnotation = fieldHasRuntimeVisibleAnnotation(f);
            if (!fieldHasRuntimeAnnotation) {
              /* only report one of these, so as not to flood the report */
              if (!hasMethodInHierarchy(cls, "toString", "()Ljava/lang/String;")) {
                bugReporter.reportBug(
                    new BugInstance(
                            this, BugType.IMC_IMMATURE_CLASS_NO_TOSTRING.name(), LOW_PRIORITY)
                        .addClass(cls));
                return;
              }
              if (heStatus != HEStatus.NOT_NEEDED) {
                String fieldSig = f.getSignature();
                if (fieldSig.startsWith("L")) {
                  if (!fieldSig.startsWith("Ljava")) {
                    JavaClass fieldClass =
                        Repository.lookupClass(fieldSig.substring(1, fieldSig.length() - 1));
                    if (!hasMethodInHierarchy(fieldClass, "equals", "(Ljava/lang/Object)Z")) {
                      heStatus = HEStatus.NOT_NEEDED;
                    }
                  } else if (!fieldSig.startsWith("Ljava/lang/")
                      && !fieldSig.startsWith("Ljava/util/")) {
                    heStatus = HEStatus.NOT_NEEDED;
                  }
                } else if (!fieldSig.startsWith("[")) {
                  heStatus = HEStatus.NEEDED;
                }
              }
            } else {
              heStatus = HEStatus.NOT_NEEDED;
            }
          }
        }

        if (!clsHasRuntimeAnnotation && (heStatus == HEStatus.NEEDED)) {
          if (!hasMethodInHierarchy(cls, "equals", "(Ljava/lang/Object;)Z")) {
            bugReporter.reportBug(
                new BugInstance(this, BugType.IMC_IMMATURE_CLASS_NO_EQUALS.name(), LOW_PRIORITY)
                    .addClass(cls));
          } else if (!hasMethodInHierarchy(cls, "hashCode", "()I")) {
            bugReporter.reportBug(
                new BugInstance(this, BugType.IMC_IMMATURE_CLASS_NO_HASHCODE.name(), LOW_PRIORITY)
                    .addClass(cls));
          }
        }

      } catch (ClassNotFoundException cnfe) {
        bugReporter.reportMissingClass(cnfe);
      }
    }
  }