private boolean hasTestMethods(JavaClass jClass) { boolean foundTest = false; Method[] methods = jClass.getMethods(); for (Method m : methods) { if (m.isPublic() && m.getName().startsWith("test") && m.getSignature().equals("()V")) { return true; } if (m.getName().startsWith("runTest") && m.getSignature().endsWith("()V")) { return true; } } if (hasSuite(methods)) { return true; } try { JavaClass sClass = jClass.getSuperClass(); if (sClass != null) { return hasTestMethods(sClass); } } catch (ClassNotFoundException e) { AnalysisContext.reportMissingClass(e); } return false; }
@Override public void visitClassContext(ClassContext classContext) { JavaClass javaClass = classContext.getJavaClass(); // The class extends WebChromeClient boolean isWebChromeClient = InterfaceUtils.isSubtype(javaClass, "android.webkit.WebChromeClient"); // Not the target of this detector if (!isWebChromeClient) return; Method[] methodList = javaClass.getMethods(); for (Method m : methodList) { MethodGen methodGen = classContext.getMethodGen(m); if (DEBUG) System.out.println(">>> Method: " + m.getName()); // The presence of onGeolocationPermissionsShowPrompt is not enforce for the moment if (!m.getName().equals("onGeolocationPermissionsShowPrompt")) { continue; } // Since the logic implemented need to be analyze by a human, all implementation will be // flagged. bugReporter.reportBug( new BugInstance(this, ANDROID_GEOLOCATION_TYPE, Priorities.NORMAL_PRIORITY) // .addClassAndMethod(javaClass, m)); } }
@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(); }
/** * overrides the visitor to find abstract methods that override concrete ones * * @param obj the context object of the currently parsed method */ @Override public void visitMethod(Method obj) { if (!obj.isAbstract()) return; String methodName = obj.getName(); String methodSig = obj.getSignature(); outer: for (JavaClass cls : superClasses) { Method[] methods = cls.getMethods(); for (Method m : methods) { if (m.isPrivate() || m.isAbstract()) continue; if (methodName.equals(m.getName()) && methodSig.equals(m.getSignature())) { BugInstance bug = new BugInstance(this, BugType.AOM_ABSTRACT_OVERRIDDEN_METHOD.name(), NORMAL_PRIORITY) .addClass(this) .addMethod(this); Code code = obj.getCode(); if (code != null) bug.addSourceLineRange(clsContext, this, 0, code.getLength() - 1); bugReporter.reportBug(bug); break outer; } } } }
/* (non-Javadoc) * @see edu.umd.cs.findbugs.classfile.IAnalysisEngine#analyze(edu.umd.cs.findbugs.classfile.IAnalysisCache, java.lang.Object) */ public Method analyze(IAnalysisCache analysisCache, MethodDescriptor descriptor) throws CheckedAnalysisException { JavaClass jclass = analysisCache.getClassAnalysis(JavaClass.class, descriptor.getClassDescriptor()); Method[] methodList = jclass.getMethods(); Method result = null; // As a side-effect, cache all of the Methods for this JavaClass for (Method method : methodList) { MethodDescriptor methodDescriptor = DescriptorFactory.instance() .getMethodDescriptor( descriptor.getSlashedClassName(), method.getName(), method.getSignature(), method.isStatic()); // Put in cache eagerly analysisCache.eagerlyPutMethodAnalysis(Method.class, methodDescriptor, method); if (methodDescriptor.equals(descriptor)) { result = method; } } return result; }
/** * Returns the name of the join point. * * @param method the method * @param methodSequence the method sequence * @return the name of the join point */ private static String getJoinPointName(final Method method, final int methodSequence) { final StringBuffer joinPoint = new StringBuffer(); joinPoint.append(TransformationUtil.MEMBER_METHOD_JOIN_POINT_PREFIX); joinPoint.append(method.getName()); joinPoint.append(TransformationUtil.DELIMITER); joinPoint.append(methodSequence); return joinPoint.toString(); }
/** * 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()); }
/** * Returns the prefixed method name. * * @param method the method * @param methodSequence the method sequence * @param className the class name * @return the name of the join point */ private String getPrefixedMethodName( final Method method, final int methodSequence, final String className) { final StringBuffer methodName = new StringBuffer(); methodName.append(TransformationUtil.ORIGINAL_METHOD_PREFIX); methodName.append(method.getName()); methodName.append(TransformationUtil.DELIMITER); methodName.append(methodSequence); methodName.append(TransformationUtil.DELIMITER); methodName.append(className.replace('.', '_')); return methodName.toString(); }
public void visitMethod(Method method) { super.visitMethod(method); // now get the MethodInfo back from the ClassInfo for // additional work. String methodId = method.getName() + method.getSignature(); OldMethodInfo mi = getITMethodInfo(methodId); if (JOPizer.dumpMgci) { // GCRT new GCRTMethodInfo(mi, method); } }
/** * Returns a string describing a method declaration. It contains the access flags (public, * private, static, etc), the return type, the method name, and the types of each of its * arguments. */ public static String get_method_declaration(Method m) { StringBuilder sb = new StringBuilder(); Formatter f = new Formatter(sb); f.format("%s %s %s (", get_access_flags(m), m.getReturnType(), m.getName()); for (Type at : m.getArgumentTypes()) { f.format("%s, ", at); } f.format(")"); return (sb.toString().replace(", )", ")")); }
/** * Constructor. * * @param method an XMethod specifying a specific method in a specific class * @throws ClassNotFoundException */ public JavaClassAndMethod(XMethod method) throws ClassNotFoundException { this.javaClass = Repository.lookupClass(method.getClassName()); for (Method m : javaClass.getMethods()) if (m.getName().equals(method.getName()) && m.getSignature().equals(method.getSignature()) && m.isStatic() == method.isStatic()) { this.method = m; return; } throw new IllegalArgumentException("Can't find " + method); }
@Override public void visitClassContext(ClassContext classContext) { JavaClass javaClass = classContext.getJavaClass(); Method[] methodList = javaClass.getMethods(); for (Method m : methodList) { MethodGen methodGen = classContext.getMethodGen(m); if (DEBUG) { System.out.println(">>> Method: " + m.getName()); } // To suspect that an invalid String representation is being build, // we identify the construction of a MessageDigest and // the use of a function that trim leading 0. boolean invokeMessageDigest = false; boolean invokeToHexString = false; ConstantPoolGen cpg = classContext.getConstantPoolGen(); if (methodGen == null || methodGen.getInstructionList() == null) { continue; // No instruction .. nothing to do } for (Iterator itIns = methodGen.getInstructionList().iterator(); itIns.hasNext(); ) { Instruction inst = ((InstructionHandle) itIns.next()).getInstruction(); if (DEBUG) { ByteCode.printOpCode(inst, cpg); } if (inst instanceof INVOKEVIRTUAL) { // MessageDigest.digest is called INVOKEVIRTUAL invoke = (INVOKEVIRTUAL) inst; if ("java.security.MessageDigest".equals(invoke.getClassName(cpg)) && "digest".equals(invoke.getMethodName(cpg))) { invokeMessageDigest = true; } } else if (inst instanceof INVOKESTATIC && invokeMessageDigest) { // The conversion must occurs after the digest was created INVOKESTATIC invoke = (INVOKESTATIC) inst; if ("java.lang.Integer".equals(invoke.getClassName(cpg)) && "toHexString".equals(invoke.getMethodName(cpg))) { invokeToHexString = true; } } } if (invokeMessageDigest && invokeToHexString) { bugReporter.reportBug( new BugInstance(this, BAD_HEXA_CONVERSION_TYPE, Priorities.NORMAL_PRIORITY) // .addClassAndMethod(javaClass, m)); } } }
/** is there a JUnit3TestSuite */ private boolean hasSuite(Method[] methods) { for (Method m : methods) { if (m.getName().equals("suite") && m.isPublic() && m.isStatic() // && m.getReturnType().equals(junit.framework.Test.class) // && m.getArgumentTypes().length == 0 && m.getSignature().equals("()Ljunit/framework/Test;")) { return true; } } return false; }
/** * looks for methods that have it's parameters all follow the form arg0, arg1, arg2, or parm0, * parm1, parm2 etc, where the method actually has code in it * * @param cls the class to check */ private void checkIDEGeneratedParmNames(JavaClass cls) { methods: for (Method m : cls.getMethods()) { if (!m.isPublic()) { continue; } String name = m.getName(); if (Values.CONSTRUCTOR.equals(name) || Values.STATIC_INITIALIZER.equals(name)) { continue; } LocalVariableTable lvt = m.getLocalVariableTable(); if (lvt == null) { continue; } if (m.getCode().getCode().length <= MAX_EMPTY_METHOD_SIZE) { continue; } int numArgs = m.getArgumentTypes().length; if (numArgs == 0) { continue; } int offset = m.isStatic() ? 0 : 1; for (int i = 0; i < numArgs; i++) { LocalVariable lv = lvt.getLocalVariable(offset + i, 0); if ((lv == null) || (lv.getName() == null)) { continue methods; } Matcher ma = ARG_PATTERN.matcher(lv.getName()); if (!ma.matches()) { continue methods; } } bugReporter.reportBug( new BugInstance( this, BugType.IMC_IMMATURE_CLASS_IDE_GENERATED_PARAMETER_NAMES.name(), NORMAL_PRIORITY) .addClass(cls) .addMethod(cls, m)); return; } }
/** * Filters the methods to be transformed. * * @param definition the definition * @param classMetaData the class meta-data * @param method the method to filter * @return boolean */ private boolean methodFilter( final AspectWerkzDefinition definition, final ClassMetaData classMetaData, final MethodMetaData methodMetaData, final Method method) { if (method.isAbstract() || method.isNative() || method.getName().equals("<init>") || method.getName().equals("<clinit>") || method.getName().startsWith(TransformationUtil.ORIGINAL_METHOD_PREFIX) || method.getName().equals(TransformationUtil.GET_META_DATA_METHOD) || method.getName().equals(TransformationUtil.SET_META_DATA_METHOD) || method.getName().equals(TransformationUtil.CLASS_LOOKUP_METHOD) || method.getName().equals(TransformationUtil.GET_UUID_METHOD)) { return true; } else if (definition.hasExecutionPointcut(classMetaData, methodMetaData)) { return false; } else if (definition.hasThrowsPointcut(classMetaData, methodMetaData)) { return false; } else { return true; } }
@Override public void visit(Method method) { super.visit(method); String methodName = method.getName(); if ("foo".equals(methodName) || "bar".equals(methodName)) { reporter.reportBug( new BugInstance("LJCU_BUG_3", Priorities.HIGH_PRIORITY) .addClass(this) .addMethod(this) .addSourceLine(this)); } }
/** Main entry for this transformer. */ public void doTransformInterface(ClassEnhancer ce, ClassGen cg) { String class_name = cg.getClassName(); ConstantPoolGen cpg = cg.getConstantPool(); checkReadClassAttributes(ce, cg, class_name, cpg); generateFieldAccessForCallout(ce, cg, class_name, cpg); generateSuperAccessors(ce, cg, class_name, cpg); HashSet<String> calloutBindings = CallinBindingManager.getCalloutBindings(class_name); if (calloutBindings == null) { if (logging) printLogMessage("\nClass " + class_name + " requires no callout adjustment."); return; } if (logging) printLogMessage("\nCallout bindings might be changing class " + class_name + ":"); HashSet<String> oldStyleBinding = new HashSet<String>(); // try new style decapsulation first (since 1.2.8): for (String calloutBinding : calloutBindings) { DecapsulationDescriptor desc = new DecapsulationDescriptor(); if (!desc.decode(calloutBinding, cg)) oldStyleBinding.add(calloutBinding); // old style attribute else if (!desc.existsAlready) ce.addMethod(desc.generate(class_name, cpg), cg); } if (oldStyleBinding.isEmpty()) return; // --> follows: old style decapsulation for remaining bindings: int pos = class_name.lastIndexOf('.'); String package_name = "NO_PACKAGE"; if (pos != -1) package_name = class_name.substring(0, pos); Method[] methods = cg.getMethods(); for (int i = 0; i < methods.length; i++) { Method m = methods[i]; String method_name = m.getName(); boolean requiresAdjustment = CallinBindingManager.requiresCalloutAdjustment( oldStyleBinding, method_name, m.getSignature()); if (requiresAdjustment) { ce.decapsulateMethod(m, cg, package_name, cpg); } } }
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); } } }
/** Creates a new method info. */ protected MethodInfo(Method m, ClassInfo c) { name = m.getName(); signature = m.getSignature(); ci = c; code = loadCode(m); exceptions = loadExceptions(m); thrownExceptionClassNames = loadThrownExceptionClassNames(m); lineNumbers = loadLineNumbers(m); maxLocals = getMaxLocals(m); maxStack = getMaxStack(m); localVariableNames = loadLocalVariableNames(m); localVariableTypes = loadLocalVariableTypes(m); modifiers = m.getModifiers(); // clinits are automatically synchronized on the class object, // and they don't let unhandled exceptions through if (name.equals("<clinit>")) { modifiers |= Modifier.SYNCHRONIZED; attrs |= IS_CLINIT | FIREWALL; } if (name.equals("<init>")) { attrs |= IS_INIT; } if (c.isInterface()) { // all interface methods are public modifiers |= Modifier.PUBLIC; } // since that's used to store the method in the ClassInfo, and to // identify it in tne InvokeInstruction, we can set it here uniqueName = getUniqueName(name, signature); globalId = mthTable.size(); mthTable.add(this); loadAnnotations(m.getAnnotationEntries()); loadParameterAnnotations(m); }
/** * 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; }
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; }
/** * overrides the visitor to reset the stack for the new method, then checks if the immutability * field is set to immutable and if so reports it * * @param obj the context object of the currently parsed method */ @Override public void visitCode(Code obj) { try { String signature = Type.getReturnType(getMethod().getSignature()).getSignature(); if (signature.startsWith("L") && CollectionUtils.isListSetMap(signature.substring(1, signature.length() - 1))) { stack.resetForMethodEntry(this); imType = ImmutabilityType.UNKNOWN; super.visitCode(obj); if ((imType == ImmutabilityType.IMMUTABLE) || (imType == ImmutabilityType.POSSIBLY_IMMUTABLE)) { Method m = getMethod(); Statistics.getStatistics() .addImmutabilityStatus(clsName, m.getName(), m.getSignature(), imType); } } } catch (ClassNotFoundException cnfe) { bugReporter.reportMissingClass(cnfe); } }
public void instrumentMethods() { if (initializationAgentClassnames.isEmpty()) { return; } Method[] methods = classfile.parsedType.getMethods(); for (int methodIndex = 0; methodIndex < methods.length; methodIndex++) { Method method = methods[methodIndex]; if (!method.getName().contains("<init>")) { continue; } try { Method newMethod = new InitializationMethodTransformer(this, method).instrumentInitializationAspects(); classfile.setChanged(); methods[methodIndex] = newMethod; } catch (Throwable t) { t.printStackTrace(); } } }
@Override public String toString() { return clazz.getClassName() + "." + method.getName(); }
@Override public void visit(Method obj) { inConstructor = "<init>".equals(obj.getName()); }
/** * Get the MethodDescriptor that (hopefully) uniqely names this method. * * @return the MethodDescriptor uniquely naming this method */ public MethodDescriptor toMethodDescriptor() { return DescriptorFactory.instance() .getMethodDescriptor( getSlashedClassName(), method.getName(), method.getSignature(), method.isStatic()); }
/** returns whether or not the specified method is a class initializer */ public static boolean is_clinit(Method m) { return (m.getName().equals("<clinit>")); }
/** returns whether or not the specified method is a constructor * */ public static boolean is_constructor(Method m) { return (m.getName().equals("<init>") || m.getName().equals("")); }
@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; } } }