📄 findbadcast2.java
字号:
// This shouldn't happen either continue; } String castSig = castType.getSignature(); if (operandType.equals(NullType.instance()) || operandNullness.isDefinitelyNull()) { SourceLineAnnotation sourceLineAnnotation = SourceLineAnnotation .fromVisitedInstruction(classContext, methodGen, sourceFile, handle); String castName = castSig.substring(1, castSig.length() - 1) .replace('/', '.'); if (!isCast) accumulator.accumulateBug(new BugInstance(this, "NP_NULL_INSTANCEOF", split ? LOW_PRIORITY : NORMAL_PRIORITY) .addClassAndMethod(methodGen, sourceFile) .addClass(castName), sourceLineAnnotation); continue; } if (!(operandType instanceof ReferenceType)) { // Shouldn't happen - illegal bytecode continue; } ReferenceType refType = (ReferenceType) operandType; if (refType.equals(castType)) { // System.out.println("self-cast to " + castType.getSignature()); continue; } String refSig = refType.getSignature(); String castSig2 = castSig; String refSig2 = refSig; while (castSig2.charAt(0) == '[' && refSig2.charAt(0) == '[') { castSig2 = castSig2.substring(1); refSig2 = refSig2.substring(1); } SourceLineAnnotation sourceLineAnnotation = SourceLineAnnotation .fromVisitedInstruction(classContext, methodGen, sourceFile, handle); if (refSig2.charAt(0) != 'L' || castSig2.charAt(0) != 'L') { if ( castSig2.charAt(0) == '[' && (refSig2.equals("Ljava/io/Serializable;") || refSig2.equals("Ljava/lang/Object;") || refSig2.equals("Ljava/lang/Cloneable;"))) continue; if ( refSig2.charAt(0) == '[' && (castSig2.equals("Ljava/io/Serializable;") || castSig2.equals("Ljava/lang/Object;") || castSig2.equals("Ljava/lang/Cloneable;"))) continue; int priority = HIGH_PRIORITY; if (split && (castSig2.endsWith("Error;") || castSig2.endsWith("Exception;"))) priority = LOW_PRIORITY; bugReporter.reportBug( new BugInstance(this, "BC_IMPOSSIBLE_CAST", priority) .addClassAndMethod(methodGen, sourceFile) .addFoundAndExpectedType(refSig, castSig) .addSourceLine(sourceLineAnnotation)); continue; } if (!operandTypeIsExact && refSig2.equals("Ljava/lang/Object;")) { continue; } if (false && isCast && haveMultipleCast.contains(sourceLineAnnotation) || !isCast && haveMultipleInstanceOf.contains(sourceLineAnnotation)) { // skip; might be due to JSR inlining continue; } String castName = castSig2.substring(1, castSig2.length() - 1) .replace('/', '.'); String refName = refSig2.substring(1, refSig2.length() - 1) .replace('/', '.'); if (vnaDataflow == null) vnaDataflow = classContext .getValueNumberDataflow(method); ValueNumberFrame vFrame = vnaDataflow.getFactAtLocation(location); if (paramValueNumberSet == null) paramValueNumberSet = getParameterValueNumbers(classContext, method, cfg); ValueNumber valueNumber = vFrame .getTopValue(); boolean isParameter = paramValueNumberSet.contains(valueNumber); BugAnnotation variable = NullDerefAndRedundantComparisonFinder.findAnnotationFromValueNumber(method, location, valueNumber, vFrame); try { JavaClass castJavaClass = Repository.lookupClass(castName); JavaClass refJavaClass = Repository.lookupClass(refName); boolean upcast = Repository.instanceOf(refJavaClass, castJavaClass); if (upcast) { if (!isCast) accumulator.accumulateBug(new BugInstance(this, "BC_VACUOUS_INSTANCEOF", NORMAL_PRIORITY) .addClassAndMethod(methodGen, sourceFile) .addFoundAndExpectedType(refSig, castSig) ,sourceLineAnnotation); } else { boolean downcast = Repository.instanceOf(castJavaClass, refJavaClass); if (!operandTypeIsExact && refName.equals("java.lang.Object") ) continue; double rank = 0.0; boolean castToConcreteCollection = concreteCollectionClasses.contains(castName) && abstractCollectionClasses.contains(refName); boolean castToAbstractCollection = abstractCollectionClasses.contains(castName) && veryAbstractCollectionClasses.contains(refName); if (!operandTypeIsExact) { rank = DeepSubtypeAnalysis.deepInstanceOf(refJavaClass, castJavaClass); if (castToConcreteCollection && rank > 0.6) rank = (rank + 0.6) /2; else if (castToAbstractCollection && rank > 0.3) rank = (rank + 0.3) /2; } if (castName.equals("java.lang.Class") && refName.equals("java.lang.reflect.Type") && !downcast) { String msg = "java.lang.Class and java.lang.reflect.Type are incompatible\n" + castJavaClass + "\n"+refJavaClass; AnalysisContext.logError(msg); BugInstance bug = new BugInstance(this, "TESTING", HIGH_PRIORITY).addClassAndMethod(methodGen, sourceFile) .addString(msg); bugReporter.reportBug(bug); downcast = true; rank = 0.99; } if (false) System.out.println("Rank:\t" + rank + "\t" + refName + "\t" + castName); boolean completeInformation = (!castJavaClass.isInterface() && !refJavaClass .isInterface()) || refJavaClass.isFinal() || castJavaClass.isFinal(); if (DEBUG) { System.out.println("cast from " + refName + " to " + castName); System.out.println(" is downcast: " + downcast); System.out.println(" operand type is exact: " + operandTypeIsExact); System.out.println(" complete information: " + completeInformation); System.out.println(" isParameter: " + valueNumber); System.out.println(" score: " + rank); } if (!downcast && completeInformation || operandTypeIsExact) bugReporter.reportBug(new BugInstance(this, isCast ? "BC_IMPOSSIBLE_CAST" : "BC_IMPOSSIBLE_INSTANCEOF", isCast ? HIGH_PRIORITY : NORMAL_PRIORITY) .addClassAndMethod(methodGen, sourceFile) .addFoundAndExpectedType(refSig, castSig) .addOptionalAnnotation(variable) .addSourceLine(sourceLineAnnotation)); else if (isCast && rank < 0.9 && variable instanceof LocalVariableAnnotation && !valueNumber.hasFlag(ValueNumber.ARRAY_VALUE) && !valueNumber.hasFlag(ValueNumber.RETURN_VALUE)) { int priority = NORMAL_PRIORITY; if (rank > 0.75) priority += 2; else if (rank > 0.5) priority += 1; else if (rank > 0.25) priority += 0; else priority--; if (DEBUG) System.out.println(" priority a: " + priority); if (methodGen.getClassName().startsWith(refName) || methodGen.getClassName().startsWith(castName)) priority += 1; if (DEBUG) System.out.println(" priority b: " + priority); if (castJavaClass.isInterface() && !castToAbstractCollection) priority++; if (DEBUG) System.out.println(" priority c: " + priority); if (castToConcreteCollection && veryAbstractCollectionClasses.contains(refName)) priority--; if (DEBUG) System.out.println(" priority d: " + priority); if (priority <= LOW_PRIORITY && !castToAbstractCollection && !castToConcreteCollection && (refJavaClass.isInterface() || refJavaClass .isAbstract())) priority++; if (DEBUG) System.out.println(" priority e: " + priority); if (DEBUG) System.out.println(" ref name: " + refName); if (methodGen.getName().equals("compareTo")) priority++; else if (methodGen.isPublic() && isParameter) priority--; if (DEBUG) System.out.println(" priority h: " + priority); if (priority < HIGH_PRIORITY) priority = HIGH_PRIORITY; if (priority <= LOW_PRIORITY) { String bug = "BC_UNCONFIRMED_CAST"; if (castToConcreteCollection) bug = "BC_BAD_CAST_TO_CONCRETE_COLLECTION"; else if (castToAbstractCollection) bug = "BC_BAD_CAST_TO_ABSTRACT_COLLECTION"; BugInstance bugInstance = new BugInstance(this, bug, priority) .addClassAndMethod(methodGen, sourceFile) .addFoundAndExpectedType(refSig, castSig) .addOptionalAnnotation(variable); accumulator.accumulateBug(bugInstance, sourceLineAnnotation ); } } } } catch (ClassNotFoundException e) { } } accumulator.reportAccumulatedBugs(); } public void report() { }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -