/** * Add a method annotation for the method which is called by given * instruction. * * @param methodGen * the method containing the call * @param inv * the InvokeInstruction * @return this object */ @Nonnull public BugInstance addCalledMethod(MethodGen methodGen, InvokeInstruction inv) { ConstantPoolGen cpg = methodGen.getConstantPool(); return addCalledMethod(cpg, inv); }
@Override public void sawOpcode(int seen) { if (seen == Const.INVOKEVIRTUAL && "finalize".equals(getNameConstantOperand()) && "()V".equals(getSigConstantOperand())) { bugAccumulator.accumulateBug( new BugInstance(this, "FI_EXPLICIT_INVOCATION", "finalize".equals(getMethodName()) && "()V".equals(getMethodSig()) ? HIGH_PRIORITY : NORMAL_PRIORITY).addClassAndMethod(this) .addCalledMethod(this), this); } if (seen == Const.INVOKESPECIAL && "finalize".equals(getNameConstantOperand())) { sawSuperFinalize = true; } } }
@Override public void sawOpcode(int seen) { if (seen == Const.INVOKEVIRTUAL && "java/util/Random".equals(getClassConstantOperand()) && (freshRandomOnTos || freshRandomOneBelowTos)) { accumulator.accumulateBug(new BugInstance(DumbMethods.this, "DMI_RANDOM_USED_ONLY_ONCE", HIGH_PRIORITY) .addClassAndMethod(DumbMethods.this).addCalledMethod(DumbMethods.this), DumbMethods.this); } freshRandomOneBelowTos = freshRandomOnTos && isRegisterLoad(); freshRandomOnTos = seen == Const.INVOKESPECIAL && "java/util/Random".equals(getClassConstantOperand()) && Const.CONSTRUCTOR_NAME.equals(getNameConstantOperand()); } }
.addCalledMethod(this).addSourceLine(this));
void check(String className, String[] methodNames, int target, int url) { if (Arrays.binarySearch(methodNames, getNameConstantOperand()) < 0) { return; } if (stack.getStackDepth() <= target) { return; } OpcodeStack.Item targetItem = stack.getStackItem(target); OpcodeStack.Item urlItem = stack.getStackItem(url); if (!"Ljava/net/URL;".equals(urlItem.getSignature())) { return; } if (!targetItem.getSignature().equals(className)) { return; } accumulator.accumulateBug(new BugInstance(this, "DMI_COLLECTION_OF_URLS", HIGH_PRIORITY).addClassAndMethod(this) .addCalledMethod(this), this); }
@Override public void sawOpcode(int seen) { if (seen == Const.INVOKEVIRTUAL && stack.getStackDepth() > 0 && "java/lang/String".equals(getClassConstantOperand())) { boolean lastIndexOf = "lastIndexOf".equals(getNameConstantOperand()); if (lastIndexOf || "indexOf".equals(getNameConstantOperand())) { int stackOff = -1; if ("(Ljava/lang/String;)I".equals(getSigConstantOperand())) { // sig: String stackOff = 0; } else if ("(Ljava/lang/String;I)I".equals(getSigConstantOperand())) { // sig: String, int stackOff = 1; } if (stackOff > -1) { OpcodeStack.Item item = stack.getStackItem(stackOff); Object o = item.getConstant(); if (o != null && ((String) o).length() == 1) { bugReporter.reportBug(new BugInstance(this, lastIndexOf ? "IIO_INEFFICIENT_LAST_INDEX_OF" : "IIO_INEFFICIENT_INDEX_OF", LOW_PRIORITY).addClassAndMethod(this) .describe(StringAnnotation.STRING_MESSAGE).addCalledMethod(this).addSourceLine(this)); } } } } }
@Override public void sawOpcode(int seen) { switch (seen) { case Const.INVOKEVIRTUAL: case Const.INVOKESPECIAL: case Const.INVOKESTATIC: XMethod callSeen = XFactory.createXMethod(MethodAnnotation.fromCalledMethod(this)); DefaultEncodingAnnotation annotation = defaultEncodingAnnotationDatabase.getDirectAnnotation(callSeen); if (annotation != null) { bugAccumulator.accumulateBug(new BugInstance(this, "DM_DEFAULT_ENCODING", HIGH_PRIORITY).addClassAndMethod(this) .addCalledMethod(this), this); } break; default: break; } } }
@Override public void sawOpcode(int seen) { if (seen == Const.INVOKEVIRTUAL && "setAccessible".equals(getNameConstantOperand())) { @DottedClassName String className = getDottedClassConstantOperand(); if ("java.lang.reflect.Field".equals(className) || "java.lang.reflect.Method".equals(className)) { bugAccumulator.accumulateBug( new BugInstance(this, "DP_DO_INSIDE_DO_PRIVILEGED", LOW_PRIORITY).addClassAndMethod(this) .addCalledMethod(this), this); } } if (seen == Const.NEW) { @DottedClassName String classOfConstructedClass = getDottedClassConstantOperand(); if (Subtypes2.instanceOf(classOfConstructedClass, "java.lang.ClassLoader") && !("main".equals(getMethodName()) && "([Ljava/lang/String;)V".equals(getMethodSig()) && getMethod() .isStatic())) { bugAccumulator.accumulateBug(new BugInstance(this, "DP_CREATE_CLASSLOADER_INSIDE_DO_PRIVILEGED", NORMAL_PRIORITY) .addClassAndMethod(this).addClass(classOfConstructedClass), this); } } }
BugInstance bug = new BugInstance(this, type, prio).addClass(this).addMethod(this).addCalledMethod(this) .addMethod(shouldCall).describe("SHOULD_CALL"); bugAccumulator.accumulateBug(bug, this);
if (it.getSpecialKind() == OpcodeStack.Item.FILE_SEPARATOR_STRING && (flags & Pattern.LITERAL) == 0) { bugReporter.reportBug(new BugInstance(this, "RE_CANT_USE_FILE_SEPARATOR_AS_REGULAR_EXPRESSION", HIGH_PRIORITY) .addClassAndMethod(this).addCalledMethod(this).addSourceLine(this)); return; .addClassAndMethod(this).addCalledMethod(this).addString(message).describe(StringAnnotation.ERROR_MSG_ROLE) .addString(regex).describe(StringAnnotation.REGEX_ROLE); String options = getOptions(flags);
accumulator.accumulateBug( new BugInstance(this, "RR_NOT_CHECKED", recentCallToAvailable ? LOW_PRIORITY : NORMAL_PRIORITY) .addClassAndMethod(this).addCalledMethod(lastCallClass, lastCallMethod, lastCallSig, false), SourceLineAnnotation.fromVisitedInstruction(getClassContext(), this, locationOfCall)); new BugInstance(this, "SR_NOT_CHECKED", (wasBufferedInputStream ? HIGH_PRIORITY : recentCallToAvailable ? LOW_PRIORITY : NORMAL_PRIORITY)).addClassAndMethod(this) .addCalledMethod(lastCallClass, lastCallMethod, lastCallSig, false), SourceLineAnnotation .fromVisitedInstruction(getClassContext(), this, locationOfCall));
private void reportBugSink(int priority, Collection<Integer> offsets) { String bugType = HARD_CODE_KEY_TYPE; for (Integer paramIndex : offsets) { OpcodeStack.Item stackItem = stack.getStackItem(paramIndex); String signature = stackItem.getSignature(); if ("Ljava/lang/String;".equals(signature) || "[C".equals(signature)) { bugType = HARD_CODE_PASSWORD_TYPE; break; } } BugInstance bugInstance = new BugInstance(this, bugType, priority) .addClass(this).addMethod(this) .addSourceLine(this).addCalledMethod(this); for (Integer paramIndex : offsets) { OpcodeStack.Item stackItem = stack.getStackItem(paramIndex); bugInstance.addParameterAnnotation(paramIndex, "Hard coded parameter number (in reverse order) is") .addFieldOrMethodValueSource(stackItem); Object constant = stackItem.getConstant(); if (constant != null) { bugInstance.addString(constant.toString()); } } bugReporter.reportBug(bugInstance); }
&& 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)); } else if (seen == Const.INVOKEINTERFACE && getMethodDescriptorOperand().equals(NODELIST_GET_LENGTH)) { Item item = getStack().getStackItem(0); matched.put(getPC(), new BugInstance(this, "IIL_ELEMENTS_GET_LENGTH_IN_LOOP", NORMAL_PRIORITY).addClassAndMethod(this) .addSourceLine(this, getPC()).addCalledMethod(this)); sources.put(getPC(), item.getPC()); String regex = getFirstArgument(); matched.put(getPC(), new BugInstance(this, "IIL_PATTERN_COMPILE_IN_LOOP", NORMAL_PRIORITY).addClassAndMethod(this) .addSourceLine(this, getPC()).addCalledMethod(this).addString(regex).describe(StringAnnotation.REGEX_ROLE)); } else if ((seen == Const.INVOKESTATIC || seen == Const.INVOKEVIRTUAL) && implicitPatternMethods.contains(getMethodDescriptorOperand())) { String regex = getFirstArgument(); if (regex != null && !(getNameConstantOperand().equals("split") && isFastPath(regex))) { BugInstance bug = new BugInstance(this, "IIL_PATTERN_COMPILE_IN_LOOP_INDIRECT", LOW_PRIORITY) .addClassAndMethod(this).addSourceLine(this, getPC()).addCalledMethod(this).addString(regex) .describe(StringAnnotation.REGEX_ROLE); matched.put(getPC(), bug);
bug.addCalledMethod(DumbMethods.this);
private void analyzeMethod(Method m, ClassContext classContext) throws CFGBuilderException, DataflowAnalysisException { MethodGen methodGen = classContext.getMethodGen(m); ConstantPoolGen cpg = classContext.getConstantPoolGen(); CFG cfg = classContext.getCFG(m); if (methodGen == null || methodGen.getInstructionList() == null) { return; //No instruction .. nothing to do } for (Iterator<Location> i = cfg.locationIterator(); i.hasNext(); ) { Location location = i.next(); Instruction inst = location.getHandle().getInstruction(); if (inst instanceof InvokeInstruction) { InvokeInstruction invoke = (InvokeInstruction) inst; String methodName = invoke.getMethodName(cpg); if ("enableDefaultTyping".equals(methodName)) { JavaClass clz = classContext.getJavaClass(); bugReporter.reportBug(new BugInstance(this, DESERIALIZATION_TYPE, HIGH_PRIORITY) .addClass(clz) .addMethod(clz, m) .addCalledMethod(cpg, invoke) .addSourceLine(classContext, m, location) ); } } } }
type.getClassName(), new BugInstance(this, "HE_USE_OF_UNHASHABLE_CLASS", priority).addClassAndMethod(this) .addTypeOfNamedClass(type.getClassName()).describe(TypeAnnotation.UNHASHABLE_ROLE).addCalledMethod(this) .addSourceLine(this));
@Override public void sawOpcode(int seen) { if (seen == Const.INVOKEVIRTUAL || seen == Const.INVOKEINTERFACE) { check("Ljava/util/HashSet;", HASHSET_KEY_METHODS, 1, 0); check("Ljava/util/HashMap;", HASHMAP_KEY_METHODS, 1, 0); check("Ljava/util/HashMap;", HASHMAP_TWO_ARG_KEY_METHODS, 2, 1); } if (seen == Const.INVOKEVIRTUAL && (getMethodDescriptorOperand().equals(URL_EQUALS) || getMethodDescriptorOperand().equals(URL_HASHCODE))) { accumulator.accumulateBug( new BugInstance(this, "DMI_BLOCKING_METHODS_ON_URL", HIGH_PRIORITY).addClassAndMethod(this) .addCalledMethod(this), this); } } }
@Override public void sawOpcode(int seen) { if (seen == Const.INVOKEVIRTUAL && "start".equals(getNameConstantOperand()) && "()V".equals(getSigConstantOperand())) { try { if (Hierarchy.isSubtype(getDottedClassConstantOperand(), "java.lang.Thread")) { int priority = Priorities.NORMAL_PRIORITY; if (getPC() + 4 >= getCode().getCode().length) { priority = Priorities.LOW_PRIORITY; } BugInstance bug = new BugInstance(this, "SC_START_IN_CTOR", priority).addClassAndMethod(this) .addCalledMethod(this); Subtypes2 subtypes2 = AnalysisContext.currentAnalysisContext().getSubtypes2(); Set<ClassDescriptor> directSubtypes = subtypes2.getDirectSubtypes(getClassDescriptor()); if (!directSubtypes.isEmpty()) { for (ClassDescriptor sub : directSubtypes) { bug.addClass(sub).describe(ClassAnnotation.SUBCLASS_ROLE); } bug.setPriority(Priorities.HIGH_PRIORITY); } bugAccumulator.accumulateBug(bug, this); } } catch (ClassNotFoundException e) { bugReporter.reportMissingClass(e); } } } }
.addCalledMethod(DumbMethods.this) .addString("Passing String constant as value that should be null checked").describe(StringAnnotation.STRING_MESSAGE) .addString((String) o).describe(StringAnnotation.STRING_CONSTANT_ROLE); .addCalledMethod(DumbMethods.this).addString("Passing String constant as value that should be null checked").describe(StringAnnotation.STRING_MESSAGE) .addString((String) o).describe(StringAnnotation.STRING_CONSTANT_ROLE); if (secondArgument != null) {
@Override public void sawOpcode(int seen) { if (seen == Const.SIPUSH) { lastConstantForSIPUSH = getIntConstant(); } if (seen == Const.INVOKEINTERFACE || seen == Const.INVOKEVIRTUAL || seen == Const.INVOKESPECIAL || seen == Const.INVOKESTATIC) { String signature = getSigConstantOperand(); int numberArguments = PreorderVisitor.getNumberArguments(signature); for (int i = 0; i < numberArguments; i++) { Item item = stack.getStackItem(numberArguments - 1 - i); if (item.getSpecialKind() == OpcodeStack.Item.RESULT_OF_I2L) { ParameterProperty property = database.getProperty(getMethodDescriptorOperand()); if (property != null && property.hasProperty(i)) { int priority = NORMAL_PRIORITY; if (getPrevOpcode(1) == Const.I2L && getPrevOpcode(2) == Const.IMUL && getPrevOpcode(3) == Const.SIPUSH && lastConstantForSIPUSH == 1000) { priority = HIGH_PRIORITY; } else if (getPrevOpcode(1) == Const.I2L && getPrevOpcode(2) == Const.IMUL && getPrevOpcode(4) == Const.SIPUSH && lastConstantForSIPUSH == 1000) { priority = HIGH_PRIORITY; } BugInstance bug = new BugInstance(this, "ICAST_INT_2_LONG_AS_INSTANT", priority).addClassAndMethod(this) .addCalledMethod(this).addValueSource(item, this).addSourceLine(this); bugReporter.reportBug(bug); } } } } }