Ejemplo n.º 1
0
 /**
  * Lookup a class. <em>Use this method instead of Repository.lookupClass().</em>
  *
  * @param className the name of the class
  * @return the JavaClass representing the class
  * @throws ClassNotFoundException (but not really)
  */
 public JavaClass lookupClass(@Nonnull @DottedClassName String className)
     throws ClassNotFoundException {
   try {
     if (className.length() == 0) {
       throw new IllegalArgumentException("Class name is empty");
     }
     if (!ClassName.isValidClassName(className)) {
       throw new ClassNotFoundException("Invalid class name: " + className);
     }
     return Global.getAnalysisCache()
         .getClassAnalysis(
             JavaClass.class,
             DescriptorFactory.instance()
                 .getClassDescriptor(ClassName.toSlashedClassName(className)));
   } catch (CheckedAnalysisException e) {
     throw new ClassNotFoundException("Class not found: " + className, e);
   }
 }
Ejemplo n.º 2
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;
    }
  }
Ejemplo n.º 3
0
 private static String getFullMethodName(ConstantPoolGen cpg, InvokeInstruction invoke) {
   String dottedClassName = invoke.getReferenceType(cpg).toString();
   StringBuilder builder = new StringBuilder(ClassName.toSlashedClassName(dottedClassName));
   builder.append(".").append(invoke.getMethodName(cpg)).append(invoke.getSignature(cpg));
   return builder.toString();
 }
Ejemplo n.º 4
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()));
 }
 private String getClassName(JavaClass c, int classIndex) {
   String name = c.getConstantPool().getConstantString(classIndex, CONSTANT_Class);
   return ClassName.extractClassName(name).replace('/', '.');
 }
 private String getSlashedClassName(FieldOrMethod obj) {
   String className = obj.getReferenceType(cpg).toString();
   return ClassName.toSlashedClassName(className);
 }
 private void handle(@SlashedClassName String className, boolean isFloatingPoint, String sig) {
   XMethod m =
       XFactory.createXMethod(ClassName.toDottedClassName(className), "valueOf", sig, true);
   boxClasses.put(className, m);
 }
Ejemplo n.º 8
0
  /*
   * (non-Javadoc)
   *
   * @see
   * edu.umd.cs.findbugs.classfile.engine.ClassParserInterface#parse(edu.umd
   * .cs.findbugs.classfile.analysis.ClassNameAndSuperclassInfo.Builder)
   */
  public void parse(final ClassNameAndSuperclassInfo.Builder cBuilder)
      throws InvalidClassFileFormatException {

    cBuilder.setCodeBaseEntry(codeBaseEntry);

    final TreeSet<ClassDescriptor> calledClassSet = new TreeSet<ClassDescriptor>();

    classReader.accept(
        new ClassVisitor() {

          boolean isInnerClass = false;

          public void visit(
              int version,
              int access,
              String name,
              String signature,
              String superName,
              String[] interfaces) {
            ClassParserUsingASM.this.slashedClassName = name;
            cBuilder.setClassfileVersion(version >>> 16, version & 0xffff);
            cBuilder.setAccessFlags(access);
            cBuilder.setClassDescriptor(DescriptorFactory.createClassDescriptor(name));
            cBuilder.setInterfaceDescriptorList(
                DescriptorFactory.createClassDescriptor(interfaces));
            if (superName != null)
              cBuilder.setSuperclassDescriptor(DescriptorFactory.createClassDescriptor(superName));
            if (cBuilder instanceof ClassInfo.Builder) {
              ((ClassInfo.Builder) cBuilder).setSourceSignature(signature);
            }
          }

          public org.objectweb.asm.AnnotationVisitor visitAnnotation(
              String desc, boolean isVisible) {
            if (cBuilder instanceof ClassInfo.Builder) {
              AnnotationValue value = new AnnotationValue(desc);
              ((ClassInfo.Builder) cBuilder).addAnnotation(desc, value);
              return value.getAnnotationVisitor();
            }
            return null;
          }

          public void visitAttribute(Attribute arg0) {
            // TODO Auto-generated method stub

          }

          public void visitEnd() {
            // TODO Auto-generated method stub

          }

          public FieldVisitor visitField(
              int access, String name, String desc, String signature, Object value) {
            if (name.equals("this$0")) isInnerClass = true;

            if (desc == null) throw new NullPointerException("Description cannot be null");
            if (cBuilder instanceof ClassInfo.Builder) {
              final ClassInfo.Builder cBuilder2 = (ClassInfo.Builder) cBuilder;
              if ((access & Opcodes.ACC_VOLATILE) != 0 || desc.contains("util/concurrent"))
                cBuilder2.setUsesConcurrency();
              final FieldInfo.Builder fBuilder =
                  new FieldInfo.Builder(slashedClassName, name, desc, access);
              fBuilder.setSourceSignature(signature);
              return new AbstractFieldAnnotationVisitor() {

                public org.objectweb.asm.AnnotationVisitor visitAnnotation(
                    final String desc, boolean visible) {
                  AnnotationValue value = new AnnotationValue(desc);
                  fBuilder.addAnnotation(desc, value);
                  return value.getAnnotationVisitor();
                }

                public void visitEnd() {
                  cBuilder2.addFieldDescriptor(fBuilder.build());
                }
              };
            }
            return null;
          }

          public void visitInnerClass(String name, String outerName, String innerName, int access) {
            if (name.equals(slashedClassName) && outerName != null) {
              if (cBuilder instanceof ClassInfo.Builder) {
                ClassDescriptor outerClassDescriptor =
                    DescriptorFactory.createClassDescriptor(outerName);
                ((ClassInfo.Builder) cBuilder).setImmediateEnclosingClass(outerClassDescriptor);
                ((ClassInfo.Builder) cBuilder).setAccessFlags(access);
              }
            }
          }

          public MethodVisitor visitMethod(
              final int access,
              final String methodName,
              final String methodDesc,
              String signature,
              String[] exceptions) {
            if (cBuilder instanceof ClassInfo.Builder) {
              final MethodInfo.Builder mBuilder =
                  new MethodInfo.Builder(slashedClassName, methodName, methodDesc, access);
              mBuilder.setSourceSignature(signature);
              mBuilder.setThrownExceptions(exceptions);
              if ((access & Opcodes.ACC_SYNCHRONIZED) != 0) mBuilder.setUsesConcurrency();

              return new AbstractMethodVisitor() {

                int variable;

                boolean sawReturn = (access & Opcodes.ACC_NATIVE) != 0;

                boolean sawNormalThrow = false;

                boolean sawUnsupportedThrow = false;

                boolean sawSystemExit = false;

                boolean sawBranch = false;

                boolean sawBackBranch = false;

                int methodCallCount = 0;

                boolean sawStubThrow = false;

                boolean justSawInitializationOfUnsupportedOperationException;

                boolean isBridge =
                    (access & Opcodes.ACC_SYNTHETIC) != 0 && (access & Opcodes.ACC_BRIDGE) != 0;

                String bridgedMethodSignature;

                State state = State.INITIAL;

                StubState stubState = StubState.INITIAL;

                boolean isAccessMethod = methodName.startsWith("access$");

                String accessOwner, accessName, accessDesc;

                boolean accessIsStatic;

                HashSet<Label> labelsSeen = new HashSet<Label>();

                @Override
                public void visitLdcInsn(Object cst) {
                  if (cst.equals("Stub!")) stubState = StubState.LOADED_STUB;
                  else stubState = StubState.INITIAL;
                }

                @Override
                public void visitInsn(int opcode) {
                  if (opcode == Opcodes.MONITORENTER) mBuilder.setUsesConcurrency();
                  if (RETURN_OPCODE_SET.get(opcode)) sawReturn = true;
                  else if (opcode == Opcodes.ATHROW) {
                    if (stubState == StubState.INITIALIZE_RUNTIME) {
                      sawStubThrow = true;
                    } else if (justSawInitializationOfUnsupportedOperationException)
                      sawUnsupportedThrow = true;
                    else sawNormalThrow = true;
                  }
                  resetState();
                }

                public void resetState() {
                  if (state != State.AFTER_METHOD_CALL) state = State.INITIAL;
                  stubState = StubState.INITIAL;
                }

                @Override
                public void visitSomeInsn() {
                  resetState();
                }

                @Override
                public void visitVarInsn(int opcode, int var) {
                  if (opcode == Opcodes.ALOAD && var == 0) state = State.THIS_LOADED;
                  else if (state == State.THIS_LOADED)
                    switch (opcode) {
                      case Opcodes.ALOAD:
                      case Opcodes.ILOAD:
                      case Opcodes.LLOAD:
                      case Opcodes.DLOAD:
                      case Opcodes.FLOAD:
                        state = State.VARIABLE_LOADED;
                        variable = var;
                    }
                  else visitSomeInsn();
                }

                public org.objectweb.asm.AnnotationVisitor visitAnnotation(
                    final String desc, boolean visible) {
                  AnnotationValue value = new AnnotationValue(desc);
                  mBuilder.addAnnotation(desc, value);
                  return value.getAnnotationVisitor();
                }

                @Override
                public void visitMethodInsn(int opcode, String owner, String name, String desc) {
                  methodCallCount++;
                  if (isAccessMethod && methodCallCount == 1) {
                    this.accessOwner = owner;
                    this.accessName = name;
                    this.accessDesc = desc;
                    this.accessIsStatic = opcode == Opcodes.INVOKESTATIC;
                  }
                  if (stubState == StubState.LOADED_STUB
                      && opcode == Opcodes.INVOKESPECIAL
                      && owner.equals("java/lang/RuntimeException")
                      && name.equals("<init>")) stubState = StubState.INITIALIZE_RUNTIME;
                  else stubState = StubState.INITIAL;
                  if (owner.startsWith("java/util/concurrent")) mBuilder.setUsesConcurrency();
                  if (opcode == Opcodes.INVOKEINTERFACE) return;

                  if (owner.charAt(0) == '[' && owner.charAt(owner.length() - 1) != ';') {
                    // primitive array
                    return;
                  }
                  if (opcode == Opcodes.INVOKESTATIC
                      && owner.equals("java/lang/System")
                      && name.equals("exit")
                      && !sawReturn) sawSystemExit = true;
                  justSawInitializationOfUnsupportedOperationException =
                      opcode == Opcodes.INVOKESPECIAL
                          && owner.equals("java/lang/UnsupportedOperationException")
                          && name.equals("<init>");

                  if (isBridge && bridgedMethodSignature == null)
                    switch (opcode) {
                      case Opcodes.INVOKEVIRTUAL:
                      case Opcodes.INVOKESPECIAL:
                      case Opcodes.INVOKESTATIC:
                      case Opcodes.INVOKEINTERFACE:
                        if (desc != null && name.equals(methodName)) bridgedMethodSignature = desc;
                    }

                  // System.out.println("Call from " +
                  // ClassParserUsingASM.this.slashedClassName +
                  // " to " + owner + " : " + desc);
                  if (desc == null || desc.indexOf('[') == -1 && desc.indexOf('L') == -1) return;
                  if (ClassParserUsingASM.this.slashedClassName.equals(owner)) return;
                  ClassDescriptor classDescriptor =
                      DescriptorFactory.instance().getClassDescriptor(owner);
                  calledClassSet.add(classDescriptor);
                  // System.out.println("Added call from " +
                  // ClassParserUsingASM.this.slashedClassName +
                  // " to " + owner);
                  state = State.AFTER_METHOD_CALL;
                }

                @Override
                public void visitJumpInsn(int opcode, Label label) {
                  sawBranch = true;
                  if (labelsSeen.contains(label)) sawBackBranch = true;
                  super.visitJumpInsn(opcode, label);
                }

                @Override
                public void visitLabel(Label label) {
                  labelsSeen.add(label);
                  super.visitLabel(label);
                }

                public void visitEnd() {
                  labelsSeen.clear();
                  if (isAccessMethod && methodCallCount == 1) {
                    mBuilder.setAccessMethodFor(
                        accessOwner, accessName, accessDesc, accessIsStatic);
                  }
                  if (sawBackBranch) mBuilder.setHasBackBranch();
                  boolean sawThrow = sawNormalThrow | sawUnsupportedThrow | sawStubThrow;
                  if (sawThrow && !sawReturn || sawSystemExit && !sawBranch) {

                    mBuilder.setIsUnconditionalThrower();
                    if (!sawReturn && !sawNormalThrow) {
                      if (sawUnsupportedThrow) mBuilder.setUnsupported();
                      if (sawStubThrow) {
                        mBuilder.addAccessFlags(Constants.ACC_SYNTHETIC);
                        mBuilder.setIsStub();
                      }
                    }
                    // else
                    // System.out.println(slashedClassName+"."+methodName+methodDesc
                    // + " is thrower");
                  }
                  mBuilder.setNumberMethodCalls(methodCallCount);
                  MethodInfo methodInfo = mBuilder.build();
                  Builder classBuilder = (ClassInfo.Builder) cBuilder;
                  if (isBridge
                      && bridgedMethodSignature != null
                      && !bridgedMethodSignature.equals(methodDesc))
                    classBuilder.addBridgeMethodDescriptor(methodInfo, bridgedMethodSignature);
                  else classBuilder.addMethodDescriptor(methodInfo);

                  if (methodInfo.usesConcurrency()) classBuilder.setUsesConcurrency();
                  if (methodInfo.isStub()) classBuilder.setHasStubs();
                }

                public org.objectweb.asm.AnnotationVisitor visitParameterAnnotation(
                    int parameter, String desc, boolean visible) {
                  AnnotationValue value = new AnnotationValue(desc);
                  mBuilder.addParameterAnnotation(parameter, desc, value);
                  return value.getAnnotationVisitor();
                }
              };
            }
            return null;
          }

          public void visitOuterClass(String owner, String name, String desc) {}

          public void visitSource(String arg0, String arg1) {
            if (cBuilder instanceof ClassInfo.Builder) {
              ((ClassInfo.Builder) cBuilder).setSource(arg0);
            }
          }
        },
        ClassReader.SKIP_FRAMES);
    HashSet<ClassDescriptor> referencedClassSet = new HashSet<ClassDescriptor>();

    // collect class references

    int constantPoolCount = classReader.readUnsignedShort(8);
    int offset = 10;
    char[] buf = new char[1024];
    // System.out.println("constant pool count: " + constantPoolCount);
    for (int count = 1; count < constantPoolCount; count++) {
      int tag = classReader.readByte(offset);

      int size;
      switch (tag) {
        case Constants.CONSTANT_Methodref:
        case Constants.CONSTANT_InterfaceMethodref:
        case Constants.CONSTANT_Fieldref:
        case Constants.CONSTANT_Integer:
        case Constants.CONSTANT_Float:
        case Constants.CONSTANT_NameAndType:
          size = 5;
          break;
        case Constants.CONSTANT_Long:
        case Constants.CONSTANT_Double:
          size = 9;
          count++;
          break;
        case Constants.CONSTANT_Utf8:
          size = 3 + classReader.readUnsignedShort(offset + 1);
          break;
        case Constants.CONSTANT_Class:
          @SlashedClassName String className = classReader.readUTF8(offset + 1, buf);
          if (className.indexOf('[') >= 0) {
            ClassParser.extractReferencedClassesFromSignature(referencedClassSet, className);
          } else if (ClassName.isValidClassName(className)) {
            ClassDescriptor classDescriptor =
                DescriptorFactory.instance().getClassDescriptor(className);
            referencedClassSet.add(classDescriptor);
          }
          size = 3;
          break;
          // case ClassWriter.CLASS:
          // case ClassWriter.STR:
        case Constants.CONSTANT_String:
          size = 3;
          break;
        default:
          throw new IllegalStateException(
              "Unexpected tag of "
                  + tag
                  + " at offset "
                  + offset
                  + " while parsing "
                  + slashedClassName
                  + " from "
                  + codeBaseEntry);
      }
      // System.out.println(count + "@" + offset + " : [" + tag
      // +"] size="+size);
      offset += size;
    }
    cBuilder.setCalledClassDescriptors(calledClassSet);
    cBuilder.setReferencedClassDescriptors(referencedClassSet);
  }