/** * 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; } } } }
public static @CheckForNull LocalVariableAnnotation findUniqueBestMatchingParameter( ClassContext classContext, Method method, String name, String signature) { LocalVariableAnnotation match = null; int localsThatAreParameters = PreorderVisitor.getNumberArguments(method.getSignature()); int startIndex = 0; if (!method.isStatic()) startIndex = 1; SignatureParser parser = new SignatureParser(method.getSignature()); Iterator<String> signatureIterator = parser.parameterSignatureIterator(); int lowestCost = Integer.MAX_VALUE; for (int i = startIndex; i < localsThatAreParameters + startIndex; i++) { String sig = signatureIterator.next(); if (signature.equals(sig)) { LocalVariableAnnotation potentialMatch = LocalVariableAnnotation.getLocalVariableAnnotation(method, i, 0, 0); if (!potentialMatch.isNamed()) continue; int distance = EditDistance.editDistance(name, potentialMatch.getName()); if (distance < lowestCost) { match = potentialMatch; match.setDescription(DID_YOU_MEAN_ROLE); lowestCost = distance; } else if (distance == lowestCost) { // not unique best match match = null; } // signatures match } } if (lowestCost < 5) return match; return null; }
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 visit(Method obj) { if (getMethodName().equals("suite") && !obj.isStatic()) { bugReporter.reportBug( new BugInstance(this, "IJU_SUITE_NOT_STATIC", NORMAL_PRIORITY).addClassAndMethod(this)); } if (getMethodName().equals("suite") && obj.getSignature().startsWith("()") && obj.isStatic()) { if ((!obj.getSignature().equals("()Ljunit/framework/Test;") && !obj.getSignature().equals("()Ljunit/framework/TestSuite;")) || !obj.isPublic()) { bugReporter.reportBug( new BugInstance(this, "IJU_BAD_SUITE_METHOD", NORMAL_PRIORITY).addClassAndMethod(this)); } } }
/* (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; }
/** * implements the visitor to reset the stack and proceed for private methods * * @param obj the context object of the currently parsed code block */ @Override public void visitCode(Code obj) { Method m = getMethod(); int aFlags = m.getAccessFlags(); if ((((aFlags & Constants.ACC_PRIVATE) != 0) || ((aFlags & Constants.ACC_STATIC) != 0)) && ((aFlags & Constants.ACC_SYNTHETIC) == 0) && (!m.getSignature().endsWith(")Z"))) { stack.resetForMethodEntry(this); returnRegister = -1; returnConstant = null; registerConstants.clear(); methodSuspect = true; returnPC = -1; super.visitCode(obj); if (methodSuspect && (returnConstant != null)) { BugInstance bi = new BugInstance( this, BugType.MRC_METHOD_RETURNS_CONSTANT.name(), ((aFlags & Constants.ACC_PRIVATE) != 0) ? NORMAL_PRIORITY : LOW_PRIORITY) .addClass(this) .addMethod(this); if (returnPC >= 0) { bi.addSourceLine(this, returnPC); } bi.addString(returnConstant.toString()); bugReporter.reportBug(bi); } } }
/** * 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()); }
public static @CheckForNull LocalVariableAnnotation findMatchingIgnoredParameter( ClassContext classContext, Method method, String name, String signature) { try { Dataflow<BitSet, LiveLocalStoreAnalysis> llsaDataflow = classContext.getLiveLocalStoreDataflow(method); CFG cfg; cfg = classContext.getCFG(method); LocalVariableAnnotation match = null; int lowestCost = Integer.MAX_VALUE; BitSet liveStoreSetAtEntry = llsaDataflow.getAnalysis().getResultFact(cfg.getEntry()); int localsThatAreParameters = PreorderVisitor.getNumberArguments(method.getSignature()); int startIndex = 0; if (!method.isStatic()) startIndex = 1; SignatureParser parser = new SignatureParser(method.getSignature()); Iterator<String> signatureIterator = parser.parameterSignatureIterator(); for (int i = startIndex; i < localsThatAreParameters + startIndex; i++) { String sig = signatureIterator.next(); if (!liveStoreSetAtEntry.get(i) && signature.equals(sig)) { // parameter isn't live and signatures match LocalVariableAnnotation potentialMatch = LocalVariableAnnotation.getLocalVariableAnnotation(method, i, 0, 0); potentialMatch.setDescription(DID_YOU_MEAN_ROLE); if (!potentialMatch.isNamed()) return potentialMatch; int distance = EditDistance.editDistance(name, potentialMatch.getName()); if (distance < lowestCost) { match = potentialMatch; match.setDescription(DID_YOU_MEAN_ROLE); lowestCost = distance; } else if (distance == lowestCost) { // not unique best match match = null; } } } return match; } catch (DataflowAnalysisException e) { AnalysisContext.logError("", e); } catch (CFGBuilderException e) { AnalysisContext.logError("", e); } return null; }
/** * 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); }
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); } }
/** 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; }
/** 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); } }
@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; } } }
/** * 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()); }
private void setup() throws Exception { // populate BT BT.addAll(manifest.getBaseTypes()); // populate BLM BLM.addAll(manifest.getBaseMethods()); // populate BLS LS.addAll(manifest.getTransformations()); // populate ELM for (Method blm : BLM) for (Annotation an : AnnotationReader.getAnnotations(blm.getAttributes())) { if (an instanceof Equivalents) { Set<Method> lms = new HashSet<Method>(); ELM.put(blm, lms); for (String lm_name : ((Equivalents) an).value().split(",")) lms.add(rlm(lm_name)); } } // populate ET, ETinv for (JavaClass bt : BT) for (Annotation an : AnnotationReader.getAnnotations(bt.getAttributes())) if (an instanceof Equivalents) { Set<JavaClass> tset = new HashSet<JavaClass>(); ET.put(bt, tset); for (String t_name : ((Equivalents) an).value().split(",")) tset.add(rlk(t_name)); for (JavaClass t : tset) { if (ETinv.containsKey(t)) throw new InvalidLibraryException( "Bad type " + t + ": already equivalent to base method " + ETinv.get(t) + "."); ETinv.put(t, bt); } } // populate VLM for (Method blm : BLM) { VLM.put(blm, new HashMap<String, Method>()); for (Method lm : ELM.get(blm)) { String vsig = lm.getSignature(); VLM.get(blm).put(vsig, lm); } } // VLM type check for (Method blm : BLM) { Map<Integer, JavaClass> bv = method2v(blm); for (Method lm : ELM.get(blm)) { Map<Integer, JavaClass> v = method2v(lm); if (!v.keySet().equals(bv.keySet())) throw new InvalidLibraryException( "Bad method " + lm + ": number of parameters differ from base method."); for (int i : v.keySet()) if (!ETinv.get(v.get(i)).equals(bv.get(i))) throw new InvalidLibraryException( "Bad method " + lm + ": argument " + i + " is incompatible with base method."); } } // populate FLS for (JavaClass t : ETinv.keySet()) FLS.put(t, new HashMap<JavaClass, Method>()); for (Method ls : LS) { Map<Integer, JavaClass> v = method2v(ls); if (!v.containsKey(-1)) throw new InvalidLibraryException("Bad transform " + ls + ": must return an object."); if (v.size() != 2) throw new InvalidLibraryException( "Bad transform " + ls + ": must take exactly one argument."); JavaClass tu = v.get(-1); JavaClass tv = v.get(0); if (!ETinv.containsKey(tu)) throw new InvalidLibraryException( "Bad transform " + ls + ": invalid source type " + tu + "."); if (!ETinv.containsKey(tv)) throw new InvalidLibraryException( "Bad transform " + ls + ": invalid dest type " + tu + "."); if (!ETinv.get(tu).equals(ETinv.get(tv))) throw new InvalidLibraryException( "Bad transform " + ls + ": source and dest types not compatible."); FLS.get(tu).put(tv, ls); } // populate CLM for (Set<Method> lms : ELM.values()) for (Method lm : lms) for (Annotation an : AnnotationReader.getAnnotations(lm.getAttributes())) /* if (an instanceof Cost) czm.put(zm, ((Cost)an).value()); */ if (an instanceof CostFn) { String zc_name = ((CostFn) an).value(); Method zc = rlm(zc_name); CLM.put(lm, zc); } // populate CLS for (Method ls : LS) // TODO check that types are equivalent? for (Annotation an : AnnotationReader.getAnnotations(ls.getAttributes())) /* if (an instanceof Cost) czs.put(zs, ((Cost)an).value()); */ if (an instanceof CostFn) { String zc_name = ((CostFn) an).value(); Method zc = rlm(zc_name); CLS.put(ls, zc); } }