/** * @param m method to check * @return true if given method is known to change its object only */ private static boolean isObjectOnlyMethod(MethodDescriptor m) { if (m.isStatic() || m.getName().equals(Const.CONSTRUCTOR_NAME) || m.getName().equals("forEach")) { return false; } String className = m.getSlashedClassName(); if(isObjectOnlyClass(className)) { return true; } if(className.startsWith("javax/xml/") && m.getName().startsWith("next")) { return true; } if ((className.startsWith("java/net/") || className.startsWith("javax/servlet")) && (m.getName().startsWith("remove") || m.getName().startsWith("add") || m.getName().startsWith("set"))) { return true; } if(OBJECT_ONLY_METHODS.contains(m)) { return true; } return false; }
/** * Returns true if given constant pool probably has a reference to any of supplied methods * Useful to exclude from analysis uninteresting classes * @param cp constant pool * @param methods methods collection * @return true if method is found */ public static boolean hasInterestingMethod(ConstantPool cp, Collection<MethodDescriptor> methods) { for(Constant c : cp.getConstantPool()) { if(c instanceof ConstantMethodref || c instanceof ConstantInterfaceMethodref) { ConstantCP desc = (ConstantCP)c; ConstantNameAndType nameAndType = (ConstantNameAndType) cp.getConstant(desc.getNameAndTypeIndex()); String className = cp.getConstantString(desc.getClassIndex(), Const.CONSTANT_Class); String name = ((ConstantUtf8)cp.getConstant(nameAndType.getNameIndex())).getBytes(); String signature = ((ConstantUtf8)cp.getConstant(nameAndType.getSignatureIndex())).getBytes(); // We don't know whether method is static thus cannot use equals int hash = FieldOrMethodDescriptor.getNameSigHashCode(name, signature); for(MethodDescriptor method : methods) { if (method.getNameSigHashCode() == hash && (method.getSlashedClassName().isEmpty() || method.getSlashedClassName().equals(className)) && method.getName().equals(name) && method.getSignature().equals(signature)) { return true; } } } } return false; }
/** * @param m method to check * @return array of argument numbers (0-based) which this method writes into or null if we don't know anything about this method */ private static int changedArg(MethodDescriptor m) { if(m.equals(ARRAY_COPY)) { return 2; } if(m.getName().equals("toArray") && m.getSignature().equals("([Ljava/lang/Object;)[Ljava/lang/Object;") && Subtypes2.instanceOf(m.getClassDescriptor(), "java.util.Collection")) { return 0; } if ((m.getName().equals("sort") || m.getName().equals("fill") || m.getName().equals("reverse") || m.getName().equals( "shuffle")) && (m.getSlashedClassName().equals("java/util/Arrays") || m.getSlashedClassName().equals("java/util/Collections"))) { return 0; } return -1; }
@Override protected void writeKey(Writer writer, MethodDescriptor method) throws IOException { writer.write(method.getClassDescriptor().toDottedClassName()); writer.write(","); writer.write(method.getName()); writer.write(","); writer.write(method.getSignature()); writer.write(","); XMethod xMethod = XFactory.createXMethod(method); writer.write(Integer.toString(xMethod.getAccessFlags() & 0xf)); } }
/** * @param methodDescriptor */ private void sawNoSideEffectCall(MethodDescriptor methodDescriptor) { if(uselessVoidCandidate && Type.getReturnType(methodDescriptor.getSignature()) == Type.VOID && !methodDescriptor.getName().equals(Const.CONSTRUCTOR_NAME)) { /* To reduce false-positives we do not mark method as useless void if it calls * another useless void method. If that another method also in the scope of our project * then we will report it instead. If there's a cycle of no-side-effect calls, then * it's probably some delegation pattern and methods can be extended in future/derived * projects to do something useful. */ uselessVoidCandidate = false; } }
public @CheckForNull MethodAnnotation getMethodCalledAnnotation(ConstantPoolGen cpg, InvokeInstruction inv) { MethodDescriptor invokedMethod = getInvokedMethod(cpg, inv); boolean standardEquals = "equals".equals(invokedMethod.getName()) && "(Ljava/lang/Object;)Z".equals(invokedMethod.getSignature()) && !invokedMethod.isStatic(); return standardEquals ? null : MethodAnnotation.fromMethodDescriptor(invokedMethod); }
/** * @param m method to check * @return true if we may assume that given unseen method has no side effect */ private static boolean hasNoSideEffectUnknown(MethodDescriptor m) { if(m.isStatic() && m.getName().equals(Const.STATIC_INITIALIZER_NAME)) { // No side effect for class initializer of unseen class return true; } if(!m.isStatic() && m.getName().equals("toString") && m.getSignature().equals("()Ljava/lang/String;")) { // We assume no side effect for unseen toString methods return true; } if(!m.isStatic() && m.getName().equals("hashCode") && m.getSignature().equals("()I")) { // We assume no side effect for unseen hashCode methods return true; } if(m.isStatic() && m.getName().equals("values") && m.getSignature().startsWith("()")) { // We assume no side effect for unseen enums return Subtypes2.instanceOf(m.getClassDescriptor(), "java.lang.Enum"); } return false; }
protected UnresolvedXMethod(MethodDescriptor m) { super(m.getClassDescriptor().getDottedClassName(), m.getName(), m.getSignature(), m.isStatic() ? Const.ACC_STATIC : 0); if (XFactory.DEBUG_UNRESOLVED) { System.out.println("Unresolved xmethod: " + this); } }
@Override public XMethod findMatchingMethod(MethodDescriptor descriptor) { return findMethod(descriptor.getName(), descriptor.getSignature(), descriptor.isStatic()); }
/** * Create a MethodAnnotation from a MethodDescriptor. * * @param methodDescriptor * the MethodDescriptor * @return the MethodAnnotation */ public static MethodAnnotation fromMethodDescriptor(MethodDescriptor methodDescriptor) { return fromForeignMethod(methodDescriptor.getSlashedClassName(), methodDescriptor.getName(), methodDescriptor.getSignature(), methodDescriptor.isStatic()); }
/** * Convenience method for generating a method signature in human readable * form. * * @param methodDescriptor * a MethodDescriptor * @return the formatted version of that signature */ public static String convertMethodSignature(MethodDescriptor methodDescriptor) { return convertMethodSignature(methodDescriptor.getClassDescriptor().toDottedClassName(), methodDescriptor.getName(), methodDescriptor.getSignature()); }
@Override public void sawOpcode(int seen) { if(seen == Const.INVOKESTATIC && getClassConstantOperand().equals("java/lang/Math") && (getMethodDescriptorOperand().getName().equals("max") || getMethodDescriptorOperand().getName().equals("min"))) { Object const1 = stack.getStackItem(0).getConstant(); Object const2 = stack.getStackItem(1).getConstant(); if(const1 != null ^ const2 != null) { n = (const1 instanceof Number) ? (Number)const1 : (Number)const2; if(getMethodDescriptorOperand().getName().equals("min")) { upperBound = n; } else {
/** * Constructor. * * @param methodDescriptor * the MethodDescriptor indicating the method it is unprofitable * to analyze */ public MethodUnprofitableException(MethodDescriptor methodDescriptor) { super("Appears unprofitable to analyze " + methodDescriptor.toString()); this.method = XFactory.createXMethod(methodDescriptor.getClassDescriptor().toDottedClassName(), methodDescriptor.getName(), methodDescriptor.getSignature(), methodDescriptor.isStatic()); }
public MatchMethodEntry(MethodDescriptor method, ObligationPolicyDatabaseActionType action, ObligationPolicyDatabaseEntryType entryType, Obligation... obligations) { this(new SubtypeTypeMatcher(method.getClassDescriptor()), new ExactStringMatcher(method.getName()), new ExactStringMatcher(method.getSignature()), method.isStatic(), action, entryType, obligations); }
tree.add(loc); System.out.println("\n\nValue number analysis for " + descriptor.getName() + descriptor.getSignature() + " {"); for (Location loc : tree) { System.out.println("\nBefore: " + vnaDataflow.getFactAtLocation(loc));
public void analyzeMethod() throws CheckedAnalysisException { if (DEBUG_METHOD != null && !methodDescriptor.getName().equals(DEBUG_METHOD)) { return;
private void reportWarning(Obligation obligation, State state, StateSet factAtExit) { String className = obligation.getClassName(); if (methodDescriptor.isStatic() && "main".equals(methodDescriptor.getName()) && "([Ljava/lang/String;)V".equals(methodDescriptor.getSignature()) && (className.contains("InputStream") || className.contains("Reader") || factAtExit.isOnExceptionPath())) { if (methodDescriptor.getName().equals(Const.CONSTRUCTOR_NAME)) { try {
break; desc = DescriptorFactory.instance().getMethodDescriptor(superClass.getClassName(), desc.getName(), desc.getSignature(), desc.isStatic());
@Override public void sawOpcode(int seen) { if (seen == Const.INVOKEINTERFACE && getClassConstantOperand().equals("java/sql/Connection") && getMethodDescriptorOperand().getName().equals("prepareStatement") && hasConstantArguments()) { matched.put(getPC(), new BugInstance(this, "IIL_PREPARE_STATEMENT_IN_LOOP", NORMAL_PRIORITY).addClassAndMethod(this) .addSourceLine(this, getPC()).addCalledMethod(this));