/** return an int on the stack, or 'defaultValue' if can't determine */ private int getIntValue(int stackDepth, int defaultValue) { if (stack.getStackDepth() < stackDepth) { return defaultValue; } OpcodeStack.Item it = stack.getStackItem(stackDepth); Object value = it.getConstant(); if (value == null || !(value instanceof Integer)) { return defaultValue; } return ((Number) value).intValue(); }
@Override public void sawOpcode(int seen) { // printOpCode(seen); if (seen == Const.INVOKEVIRTUAL) { String fullClassName = getClassConstantOperand(); String method = getNameConstantOperand(); if(isVulnerableClassToPrint(fullClassName) && method.equals("printStackTrace")) { if (stack.getStackDepth() > 1) { // If has parameters OpcodeStack.Item parameter = stack.getStackItem(0); if (parameter.getSignature().equals("Ljava/io/PrintStream;") || parameter.getSignature().equals("Ljava/io/PrintWriter;")) { bugReporter.reportBug(new BugInstance(this, INFORMATION_EXPOSURE_THROUGH_AN_ERROR_MESSAGE_TYPE, Priorities.NORMAL_PRIORITY) .addClass(this).addMethod(this).addSourceLine(this)); } } else { // No parameter (only printStackTrace) bugReporter.reportBug(new BugInstance(this, INFORMATION_EXPOSURE_THROUGH_AN_ERROR_MESSAGE_TYPE, Priorities.LOW_PRIORITY) .addClass(this).addMethod(this).addSourceLine(this)); } } } }
@Override public void sawOpcode(int seen) { if (seen == Const.INVOKEINTERFACE) { String methodName = getNameConstantOperand(); String clsConstant = getClassConstantOperand(); if (("java/sql/ResultSet".equals(clsConstant) && ((methodName.startsWith("get") && dbFieldTypesSet .contains(methodName.substring(3))) || (methodName.startsWith("update") && dbFieldTypesSet .contains(methodName.substring(6))))) || (("java/sql/PreparedStatement".equals(clsConstant) && ((methodName.startsWith("set") && dbFieldTypesSet .contains(methodName.substring(3))))))) { String signature = getSigConstantOperand(); int numParms = PreorderVisitor.getNumberArguments(signature); if (stack.getStackDepth() >= numParms) { OpcodeStack.Item item = stack.getStackItem(numParms - 1); if ("I".equals(item.getSignature()) && item.couldBeZero()) { bugReporter.reportBug(new BugInstance(this, "java/sql/PreparedStatement".equals(clsConstant) ? "SQL_BAD_PREPARED_STATEMENT_ACCESS" : "SQL_BAD_RESULTSET_ACCESS", item.mustBeZero() ? HIGH_PRIORITY : NORMAL_PRIORITY) .addClassAndMethod(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); }
&& stack.getStackDepth() > 0) { OpcodeStack.Item item0 = stack.getStackItem(0); if (item0.getSignature().charAt(0) == '[') { bugReporter.reportBug(new BugInstance(this, "DMI_INVOKING_HASHCODE_ON_ARRAY", NORMAL_PRIORITY) .addClassAndMethod(this).addValueSource(item0, this).addSourceLine(this)); if (stack.getStackDepth() > 1) { OpcodeStack.Item item0 = stack.getStackItem(0); if (seen == Const.IADD && (getNextOpcode() == Const.ISHL || getNextOpcode() == Const.LSHL) && stack.getStackDepth() >=3) { shiftOfNonnegativeValue = false; if ((seen == Const.IUSHR || seen == Const.ISHR || seen == Const.ISHL)) { if (stack.getStackDepth() <= 1) { if (seen == Const.INVOKEVIRTUAL && stack.getStackDepth() > 0 && ("java/util/Date".equals(getClassConstantOperand()) || "java/sql/Date".equals(getClassConstantOperand())) && "setMonth".equals(getNameConstantOperand()) && "(I)V".equals(getSigConstantOperand())) { if (seen == Const.INVOKEVIRTUAL && stack.getStackDepth() > 1 && "java/util/Calendar".equals(getClassConstantOperand()) && "set".equals(getNameConstantOperand()) || seen == Const.INVOKESPECIAL && stack.getStackDepth() > 1 && "java/util/GregorianCalendar".equals(getClassConstantOperand()) && Const.CONSTRUCTOR_NAME.equals(getNameConstantOperand()) && stack.getStackDepth() > 0 && ("toString".equals(getNameConstantOperand()) && "()Ljava/lang/String;".equals(getSigConstantOperand()) || "append".equals(getNameConstantOperand())
if (hasSideEffect(seen)) { reset(); } else if (stack.getStackDepth() == 0) { if (emptyStackLocations.size() > 1) { for(int n=1; n<=emptyStackLocations.size()/2; n++) { BugInstance bug = new BugInstance(this, "RpC_REPEATED_CONDITIONAL_TEST", priority).addClassAndMethod(this) .add(firstSourceLine).add(secondSourceLine); bugReporter.reportBug(bug);
MethodAnnotation preferred = new MethodAnnotation("java.lang.Long", "parseLong", "(Ljava/lang/String;)J", true); OpcodeStack.Item left = stack.getStackItem(1); if (stack.getStackDepth() >= 2) { switch (seen) { case Const.IF_ICMPEQ: if (seen == Const.IFLT && stack.getStackDepth() > 0 && stack.getStackItem(0).getSpecialKind() == OpcodeStack.Item.SIGNED_BYTE) { sawCheckForNonNegativeSignedByte = getPC(); if (stack.getStackDepth() >= 1 && (seen == Const.LOOKUPSWITCH || seen == Const.TABLESWITCH)) { if (stack.getStackDepth() >= 2) { switch (seen) { case Const.IF_ICMPEQ: case Const.IFGE: case Const.IFLT: if(stack.getStackDepth() > 0 && stack.getStackItem(0).getSpecialKind() == OpcodeStack.Item.NON_NEGATIVE) { } else if ((seen == Const.IOR || seen == Const.LOR || seen == Const.IADD || seen == Const.LADD) && stack.getStackDepth() >= 2) { && "(Ljava/lang/Class;)Z".equals(getSigConstantOperand()) && stack.getStackDepth() > 0) { && "()Z".equals(getMethodSig()) && stack.getStackDepth() > 0) { .addString(bigDecimalString).addSourceLine(this));
throw new IllegalArgumentException("Password masking requires stack depth 1, but is " + stackDepth); if (stack.getStackDepth() < stackDepth) { return; OpcodeStack.Item it = stack.getStackItem(stackDepth); Object value = it.getConstant(); if (value == null || !(value instanceof String)) { if (ignorePasswordMasking && dotIsUsed) { priority = NORMAL_PRIORITY; OpcodeStack.Item top = stack.getStackItem(0); Object topValue = top.getConstant(); if (topValue instanceof String) { bugReporter.reportBug(new BugInstance(this, "RE_POSSIBLE_UNINTENDED_PATTERN", priority).addClassAndMethod(this) .addCalledMethod(this).addSourceLine(this));
@Override public void sawOpcode(int seen) { if(getStack().getStackDepth() == 0) { this.lastEmptyStackPC = getPC(); if((seen == Const.DCMPG || seen == Const.DCMPL || seen == Const.FCMPL || seen == Const.FCMPG) && getStack().getStackDepth() == 2) { int[] startEnd = new int[] {this.lastEmptyStackPC, getPC()}; for(Iterator<int[]> iterator = twoDoublesInStack.iterator(); iterator.hasNext(); ) { int[] oldStartEnd = iterator.next(); if(codeEquals(oldStartEnd, startEnd)) { Item item1 = getStack().getStackItem(0); Item item2 = getStack().getStackItem(1); accumulator.accumulateBug( new BugInstance("CO_COMPARETO_INCORRECT_FLOATING", NORMAL_PRIORITY).addClassAndMethod(this) .addType(item1.getSignature()) .addMethod(item1.getSignature().equals("D")?DOUBLE_DESCRIPTOR:FLOAT_DESCRIPTOR).describe(MethodAnnotation.SHOULD_CALL) .addValueSource(item1, this) .addValueSource(item2, this), this); OpcodeStack.Item top = stack.getStackItem(0); Object o = top.getConstant(); if (o instanceof Integer && ((Integer)o).intValue() == Integer.MIN_VALUE) { accumulator.accumulateBug( new BugInstance(this, "CO_COMPARETO_RESULTS_MIN_VALUE", NORMAL_PRIORITY).addClassAndMethod(this), this);
@Override public void afterOpcode(int seen) { super.afterOpcode(seen); switch (seen) { case Const.IAND: case Const.LAND: case Const.IOR: case Const.LOR: if(stack.getStackDepth() > 0) { bitresultItem = stack.getStackItem(0); } break; default: break; } }
private void bitSetSilliness(String methodName) { if (("clear".equals(methodName) || "flip".equals(methodName) || "get".equals(methodName) || "set".equals(methodName)) && (stack.getStackDepth() > 0)) { OpcodeStack.Item item = stack.getStackItem(0); Object o = item.getConstant(); if ((o instanceof Integer) && (((Integer) o).intValue() < 0)) { bugReporter.reportBug( new BugInstance(this, BugType.SPP_NEGATIVE_BITSET_ITEM.name(), NORMAL_PRIORITY).addClass(this).addMethod(this).addSourceLine(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)); } } } } }
OpcodeStack.Item left = stack.getStackItem(1); OpcodeStack.Item right = stack.getStackItem(0); if (badUseOfCompareResult(left, right)) { XMethod returnValueOf = left.getReturnValueOf(); assert returnValueOf != null; bugAccumulator.accumulateBug(new BugInstance(this, "RV_CHECK_COMPARETO_FOR_SPECIFIC_RETURN_VALUE", NORMAL_PRIORITY) .addClassAndMethod(this).addMethod(returnValueOf).describe(MethodAnnotation.METHOD_CALLED).addValueSource(right, this), this); } else if (badUseOfCompareResult(right, left)) { XMethod returnValueOf = right.getReturnValueOf(); assert returnValueOf != null; bugAccumulator.accumulateBug(new BugInstance(this, "RV_CHECK_COMPARETO_FOR_SPECIFIC_RETURN_VALUE", NORMAL_PRIORITY) .addClassAndMethod(this).addMethod(returnValueOf).describe(MethodAnnotation.METHOD_CALLED).addValueSource(left, this), this); OpcodeStack.Item invokedOn = stack.getStackItem(arguments); if (invokedOn.isNewlyAllocated() && (!Const.CONSTRUCTOR_NAME.equals(getMethodName()) || invokedOn.getRegisterNumber() != 0)) { for (int i = arguments + 1; i < stack.getStackDepth(); i++) { OpcodeStack.Item item = stack.getStackItem(i); if (item.isNewlyAllocated() && item.getSignature().equals(invokedOn.getSignature())) { priority++; bugAccumulator.accumulateBug(new BugInstance(this, annotation.getPattern(), priority).addClassAndMethod(this) .addCalledMethod(this), this);
private void markHardCodedItemsFromFlow() { for (int i = 0; i < stack.getStackDepth(); i++) { OpcodeStack.Item stackItem = stack.getStackItem(i); if ((stackItem.getConstant() != null || stackItem.isNull()) && !stackItem.getSignature().startsWith("[")) { setHardCodedItem(stackItem); } if (hasHardCodedFieldSource(stackItem)) { setHardCodedItem(stackItem); } } }
private void bitSetSilliness(String methodName) { if (("clear".equals(methodName) || "flip".equals(methodName) || "get".equals(methodName) || "set".equals(methodName)) && (stack.getStackDepth() > 0)) { OpcodeStack.Item item = stack.getStackItem(0); Object o = item.getConstant(); if ((o instanceof Integer) && (((Integer) o).intValue() < 0)) { bugReporter.reportBug( new BugInstance(this, BugType.SPP_NEGATIVE_BITSET_ITEM.name(), NORMAL_PRIORITY).addClass(this).addMethod(this).addSourceLine(this)); } } }
if (stack.getStackDepth() < stackDepth) { state = FormatState.NONE; stackDepth = 0; arguments = null; if (seen == Const.ANEWARRAY && stack.getStackDepth() >= 2) { Object size = stack.getStackItem(0).getConstant(); Object formatStr = stack.getStackItem(1).getConstant(); if (size instanceof Integer && formatStr instanceof String) { arguments = new OpcodeStack.Item[(Integer) size]; this.formatString = (String) formatStr; state = FormatState.READY_FOR_FORMAT; stackDepth = stack.getStackDepth(); } else if (state == FormatState.EXPECTING_ASSIGNMENT && stack.getStackDepth() == stackDepth + 3 && seen == Const.AASTORE) { Object pos = stack.getStackItem(1).getConstant(); OpcodeStack.Item value = stack.getStackItem(0); if (pos instanceof Integer) { && stack.getStackDepth() == stackDepth) { bugReporter.reportBug(new BugInstance(this, "VA_FORMAT_STRING_USES_NEWLINE", NORMAL_PRIORITY) .addClassAndMethod(this).addCalledMethod(this).addString(formatString) .describe(StringAnnotation.FORMAT_STRING_ROLE).addSourceLine(this));
if (stack.getStackDepth() >= 2) { Item left = stack.getStackItem(1); XMethod leftM = left.getReturnValueOf(); Item right = stack.getStackItem(0); XMethod rightM = right.getReturnValueOf(); if ("Ljava/lang/Class;".equals(left.getSignature()) && "Ljava/lang/Class;".equals(right.getSignature())) { BugInstance bug = new BugInstance(this, "EQ_GETCLASS_AND_CLASS_CONSTANT", priority) .addClassAndMethod(this); bug.addClass(c).describe(ClassAnnotation.SUBCLASS_ROLE); priority--; bug.setPriority(priority);
switch (seen) { case Const.ATHROW: if (stack.getStackDepth() > 0) { OpcodeStack.Item item = stack.getStackItem(0); String signature = item.getSignature(); if (signature != null && signature.length() > 0) {
/** * looks for containers where a null layout is installed * * @param className * class that a method call is made on * @param methodName * name of the method that is called */ private void processNullLayouts(String className, String methodName) { if ("java/awt/Container".equals(className) && "setLayout".equals(methodName) && (stack.getStackDepth() > 0) && stack.getStackItem(0).isNull()) { bugReporter.reportBug(new BugInstance(this, BugType.S508C_NULL_LAYOUT.name(), NORMAL_PRIORITY).addClass(this).addMethod(this).addSourceLine(this)); } }
private void sawRegExPattern(int stackDepth, int flags) { if (stack.getStackDepth() < stackDepth) { return; OpcodeStack.Item it = stack.getStackItem(stackDepth); 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; message = message.substring(0, eol); BugInstance bug = new BugInstance(this, "RE_BAD_SYNTAX_FOR_REGULAR_EXPRESSION", HIGH_PRIORITY) .addClassAndMethod(this).addCalledMethod(this).addString(message).describe(StringAnnotation.ERROR_MSG_ROLE) .addString(regex).describe(StringAnnotation.REGEX_ROLE); bug.addString("Regex flags: " + options).describe(StringAnnotation.STRING_MESSAGE); bug.addSourceLine(this); bugReporter.reportBug(bug);