1 19 20 package edu.umd.cs.findbugs.detect; 21 22 23 import edu.umd.cs.findbugs.*; 24 import edu.umd.cs.findbugs.ba.*; 25 import edu.umd.cs.findbugs.ba.type.*; 26 import edu.umd.cs.findbugs.props.*; 27 import java.util.*; 28 import org.apache.bcel.Constants; 29 import org.apache.bcel.classfile.*; 30 import org.apache.bcel.generic.*; 31 32 44 public class FindRefComparison implements Detector, ExtendedTypes { 45 private static final boolean DEBUG = SystemProperties.getBoolean("frc.debug"); 46 private static final boolean REPORT_ALL_REF_COMPARISONS = SystemProperties.getBoolean("findbugs.refcomp.reportAll"); 47 private static final int BASE_ES_PRIORITY = SystemProperties.getInteger("es.basePriority", NORMAL_PRIORITY); 48 49 52 private static final HashSet<String > suspiciousSet = new HashSet<String >(); 53 54 static { 55 suspiciousSet.add("java.lang.Boolean"); 56 suspiciousSet.add("java.lang.Byte"); 57 suspiciousSet.add("java.lang.Character"); 58 suspiciousSet.add("java.lang.Double"); 59 suspiciousSet.add("java.lang.Float"); 60 suspiciousSet.add("java.lang.Integer"); 61 suspiciousSet.add("java.lang.Long"); 62 suspiciousSet.add("java.lang.Short"); 63 } 64 65 68 private static final BitSet invokeInstanceSet = new BitSet(); 69 70 static { 71 invokeInstanceSet.set(Constants.INVOKEVIRTUAL); 72 invokeInstanceSet.set(Constants.INVOKEINTERFACE); 73 invokeInstanceSet.set(Constants.INVOKESPECIAL); 74 } 75 76 79 private static final BitSet prescreenSet = new BitSet(); 80 81 static { 82 prescreenSet.or(invokeInstanceSet); 83 prescreenSet.set(Constants.IF_ACMPEQ); 84 prescreenSet.set(Constants.IF_ACMPNE); 85 } 86 87 90 91 private static final byte T_DYNAMIC_STRING = T_AVAIL_TYPE + 0; 92 private static final byte T_STATIC_STRING = T_AVAIL_TYPE + 1; 93 private static final byte T_PARAMETER_STRING = T_AVAIL_TYPE + 2; 94 95 private static final String STRING_SIGNATURE = "Ljava/lang/String;"; 96 97 102 private static class DynamicStringType extends ObjectType { 103 private static final long serialVersionUID = 1L; 104 105 public DynamicStringType() { 106 super("java.lang.String"); 107 } 108 109 @Override 110 public byte getType() { 111 return T_DYNAMIC_STRING; 112 } 113 114 @Override 115 public int hashCode() { 116 return System.identityHashCode(this); 117 } 118 119 @Override 120 public boolean equals(Object o) { 121 return o == this; 122 } 123 124 @Override 125 public String toString() { 126 return "<dynamic string>"; 127 } 128 } 129 130 private static final Type dynamicStringTypeInstance = new DynamicStringType(); 131 132 138 private static class StaticStringType extends ObjectType { 139 private static final long serialVersionUID = 1L; 140 141 public StaticStringType() { 142 super("java.lang.String"); 143 } 144 145 @Override 146 public byte getType() { 147 return T_STATIC_STRING; 148 } 149 150 @Override 151 public int hashCode() { 152 return System.identityHashCode(this); 153 } 154 155 @Override 156 public boolean equals(Object o) { 157 return o == this; 158 } 159 160 @Override 161 public String toString() { 162 return "<static string>"; 163 } 164 } 165 166 private static final Type staticStringTypeInstance = new StaticStringType(); 167 168 171 private static class ParameterStringType extends ObjectType { 172 private static final long serialVersionUID = 1L; 173 174 public ParameterStringType() { 175 super("java.lang.String"); 176 } 177 178 @Override 179 public byte getType() { 180 return T_PARAMETER_STRING; 181 } 182 183 @Override 184 public int hashCode() { 185 return System.identityHashCode(this); 186 } 187 188 @Override 189 public boolean equals(Object o) { 190 return o == this; 191 } 192 193 @Override 194 public String toString() { 195 return "<parameter string>"; 196 } 197 } 198 199 private static final Type parameterStringTypeInstance = new ParameterStringType(); 200 201 private static class RefComparisonTypeFrameModelingVisitor extends TypeFrameModelingVisitor { 202 private RepositoryLookupFailureCallback lookupFailureCallback; 203 private boolean sawStringIntern; 204 205 public RefComparisonTypeFrameModelingVisitor( 206 ConstantPoolGen cpg, 207 RepositoryLookupFailureCallback lookupFailureCallback) { 208 super(cpg); 209 this.lookupFailureCallback = lookupFailureCallback; 210 this.sawStringIntern = false; 211 } 212 213 public boolean sawStringIntern() { 214 return sawStringIntern; 215 } 216 217 220 @Override 221 public void visitINVOKESTATIC(INVOKESTATIC obj) { 222 consumeStack(obj); 223 if (returnsString(obj)) { 224 String className = obj.getClassName(getCPG()); 225 if (className.equals("java.lang.String")) { 226 pushValue(dynamicStringTypeInstance); 227 } else { 228 pushReturnType(obj); 229 } 230 } else { 231 pushReturnType(obj); 232 } 233 } 234 235 @Override 236 public void visitINVOKESPECIAL(INVOKESPECIAL obj) { 237 handleInstanceMethod(obj); 238 } 239 240 @Override 241 public void visitINVOKEINTERFACE(INVOKEINTERFACE obj) { 242 handleInstanceMethod(obj); 243 } 244 245 @Override 246 public void visitINVOKEVIRTUAL(INVOKEVIRTUAL obj) { 247 handleInstanceMethod(obj); 248 } 249 250 private boolean returnsString(InvokeInstruction inv) { 251 String methodSig = inv.getSignature(getCPG()); 252 return methodSig.endsWith(")Ljava/lang/String;"); 253 } 254 255 private void handleInstanceMethod(InvokeInstruction obj) { 256 consumeStack(obj); 257 if (returnsString(obj)) { 258 String className = obj.getClassName(getCPG()); 259 String methodName = obj.getName(getCPG()); 260 262 if (methodName.equals("intern") && className.equals("java.lang.String")) { 263 sawStringIntern = true; 264 pushValue(staticStringTypeInstance); 265 } else if (methodName.equals("toString") 266 || className.equals("java.lang.String")) { 267 pushValue(dynamicStringTypeInstance); 268 } else 270 pushReturnType(obj); 271 } else 272 pushReturnType(obj); 273 } 274 275 @Override 276 public void visitLDC(LDC obj) { 277 Type type = obj.getType(getCPG()); 278 pushValue(isString(type) ? staticStringTypeInstance : type); 279 } 280 281 @Override 282 public void visitLDC2_W(LDC2_W obj) { 283 Type type = obj.getType(getCPG()); 284 pushValue(isString(type) ? staticStringTypeInstance : type); 285 } 286 287 private boolean isString(Type type) { 288 return type.getSignature().equals(STRING_SIGNATURE); 289 } 290 291 @Override 292 public void visitGETSTATIC(GETSTATIC obj) { 293 handleLoad(obj); 294 } 295 296 @Override 297 public void visitGETFIELD(GETFIELD obj) { 298 handleLoad(obj); 299 } 300 301 private void handleLoad(FieldInstruction obj) { 302 consumeStack(obj); 303 304 Type type = obj.getType(getCPG()); 305 if (type.getSignature().equals(STRING_SIGNATURE)) { 306 try { 307 String className = obj.getClassName(getCPG()); 308 String fieldName = obj.getName(getCPG()); 309 Field field = Hierarchy.findField(className, fieldName); 310 311 if (field != null) { 312 if (field.isFinal()) 315 pushValue(staticStringTypeInstance); 316 else 317 pushValue(type); 318 319 return; 320 } 321 } catch (ClassNotFoundException ex) { 322 lookupFailureCallback.reportMissingClass(ex); 323 } 324 } 325 326 pushValue(type); 327 } 328 } 329 330 333 private static class RefComparisonTypeMerger extends StandardTypeMerger { 334 public RefComparisonTypeMerger(RepositoryLookupFailureCallback lookupFailureCallback, 335 ExceptionSetFactory exceptionSetFactory) { 336 super(lookupFailureCallback, exceptionSetFactory); 337 } 338 339 @Override 340 protected boolean isReferenceType(byte type) { 341 return super.isReferenceType(type) || type == T_STATIC_STRING || type == T_DYNAMIC_STRING; 342 } 343 344 @Override 345 protected Type mergeReferenceTypes(ReferenceType aRef, ReferenceType bRef) throws DataflowAnalysisException { 346 byte aType = aRef.getType(); 347 byte bType = bRef.getType(); 348 349 if (isExtendedStringType(aType) || isExtendedStringType(bType)) { 350 if (aType == bType) 355 return aRef; 356 357 if (isExtendedStringType(aType)) 358 aRef = Type.STRING; 359 if (isExtendedStringType(bType)) 360 bRef = Type.STRING; 361 } 362 363 return super.mergeReferenceTypes(aRef, bRef); 364 } 365 366 private boolean isExtendedStringType(byte type) { 367 return type == T_DYNAMIC_STRING || type == T_STATIC_STRING || type == T_PARAMETER_STRING; 368 } 369 } 370 371 374 375 private BugReporter bugReporter; 376 private ClassContext classContext; 377 378 381 382 public FindRefComparison(BugReporter bugReporter) { 383 this.bugReporter = bugReporter; 384 } 385 386 public void visitClassContext(ClassContext classContext) { 387 this.classContext = classContext; 388 389 JavaClass jclass = classContext.getJavaClass(); 390 Method[] methodList = jclass.getMethods(); 391 392 for (Method method : methodList) { 393 MethodGen methodGen = classContext.getMethodGen(method); 394 if (methodGen == null) 395 continue; 396 397 BitSet bytecodeSet = classContext.getBytecodeSet(method); 400 if (bytecodeSet == null || !bytecodeSet.intersects(prescreenSet)) 401 continue; 402 403 if (DEBUG) 404 System.out.println("FindRefComparison: analyzing " + 405 SignatureConverter.convertMethodSignature(methodGen)); 406 407 try { 408 analyzeMethod(classContext, method); 409 } catch (CFGBuilderException e) { 410 bugReporter.logError("Error analyzing " + method.toString(), e); 411 } catch (DataflowAnalysisException e) { 412 } 414 } 415 } 416 417 420 private static class WarningWithProperties { 421 BugInstance instance; 422 WarningPropertySet propertySet; 423 Location location; 424 425 WarningWithProperties(BugInstance warning, WarningPropertySet propertySet, Location location) { 426 this.instance = warning; 427 this.propertySet = propertySet; 428 this.location = location; 429 } 430 } 431 432 private interface WarningDecorator { 433 public void decorate(WarningWithProperties warn); 434 } 435 436 private void analyzeMethod(ClassContext classContext, final Method method) 437 throws CFGBuilderException, DataflowAnalysisException { 438 439 MethodGen methodGen = classContext.getMethodGen(method); 440 if (methodGen == null) return; 441 boolean sawCallToEquals = false; 442 JavaClass jclass = classContext.getJavaClass(); 443 ConstantPoolGen cpg = classContext.getConstantPoolGen(); 444 445 446 LinkedList<WarningWithProperties> refComparisonList = 451 new LinkedList<WarningWithProperties>(); 452 LinkedList<WarningWithProperties> stringComparisonList = 453 new LinkedList<WarningWithProperties>(); 454 455 CFG cfg = classContext.getCFG(method); 456 DepthFirstSearch dfs = classContext.getDepthFirstSearch(method); 457 ExceptionSetFactory exceptionSetFactory = 458 classContext.getExceptionSetFactory(method); 459 460 RefComparisonTypeMerger typeMerger = 464 new RefComparisonTypeMerger(bugReporter, exceptionSetFactory); 465 RefComparisonTypeFrameModelingVisitor visitor = 466 new RefComparisonTypeFrameModelingVisitor(methodGen.getConstantPool(), bugReporter); 467 TypeAnalysis typeAnalysis = 468 new TypeAnalysis(methodGen, cfg, dfs, typeMerger, visitor, bugReporter, exceptionSetFactory) { 469 @Override public void initEntryFact(TypeFrame result) { 470 super.initEntryFact(result); 471 for(int i = 0; i < methodGen.getMaxLocals(); i++) { 472 Type t = result.getValue(i); 473 if (t.equals(ObjectType.STRING)) 474 result.setValue(i, parameterStringTypeInstance); 475 } 476 } 477 }; 478 TypeDataflow typeDataflow = new TypeDataflow(cfg, typeAnalysis); 479 typeDataflow.execute(); 480 481 for (Iterator<Location> i = cfg.locationIterator(); i.hasNext();) { 483 Location location = i.next(); 484 485 sawCallToEquals = inspectLocation( 486 sawCallToEquals, 487 jclass, 488 cpg, 489 methodGen, 490 refComparisonList, 491 stringComparisonList, 492 visitor, 493 typeDataflow, 494 location); 495 } 496 497 final boolean sawEquals = sawCallToEquals; 499 decorateWarnings(stringComparisonList, new WarningDecorator(){ 500 public void decorate(WarningWithProperties warn) { 501 if (sawEquals) { 502 warn.propertySet.addProperty(RefComparisonWarningProperty.SAW_CALL_TO_EQUALS); 503 } 504 505 if (false && !(method.isPublic() || method.isProtected())) { 506 warn.propertySet.addProperty(RefComparisonWarningProperty.PRIVATE_METHOD); 507 } 508 } 509 }); 510 decorateWarnings(refComparisonList, new WarningDecorator() { 511 public void decorate(WarningWithProperties warn) { 512 if (sawEquals) { 513 warn.propertySet.addProperty(RefComparisonWarningProperty.SAW_CALL_TO_EQUALS); 514 } 515 } 516 }); 517 518 boolean relaxed = FindBugsAnalysisFeatures.isRelaxedMode(); 520 reportBest(classContext, method, stringComparisonList, relaxed); 521 reportBest(classContext, method, refComparisonList, relaxed); 522 } 523 524 private boolean inspectLocation( 525 boolean sawCallToEquals, 526 JavaClass jclass, 527 ConstantPoolGen cpg, 528 MethodGen methodGen, 529 LinkedList<WarningWithProperties> refComparisonList, 530 LinkedList<WarningWithProperties> stringComparisonList, 531 RefComparisonTypeFrameModelingVisitor visitor, 532 TypeDataflow typeDataflow, 533 Location location) throws DataflowAnalysisException { 534 Instruction ins = location.getHandle().getInstruction(); 535 short opcode = ins.getOpcode(); 536 if (opcode == Constants.IF_ACMPEQ || opcode == Constants.IF_ACMPNE) { 537 checkRefComparison( 538 location, 539 jclass, 540 methodGen, 541 visitor, 542 typeDataflow, 543 stringComparisonList, 544 refComparisonList); 545 } else if (invokeInstanceSet.get(opcode)) { 546 InvokeInstruction inv = (InvokeInstruction) ins; 547 String methodName = inv.getMethodName(cpg); 548 String methodSig = inv.getSignature(cpg); 549 if (isEqualsMethod(methodName, methodSig)) { 550 sawCallToEquals = true; 551 checkEqualsComparison(location, jclass, methodGen, typeDataflow); 552 } 553 } 554 return sawCallToEquals; 555 } 556 557 private void decorateWarnings( 558 LinkedList<WarningWithProperties> stringComparisonList, 559 WarningDecorator warningDecorator) { 560 for (WarningWithProperties warn : stringComparisonList) { 561 warningDecorator.decorate(warn); 562 warn.instance.setPriority(warn.propertySet.computePriority(NORMAL_PRIORITY)); 563 } 564 } 565 566 private void reportBest( 567 ClassContext classContext, 568 Method method, 569 LinkedList<WarningWithProperties> warningList, 570 boolean relaxed) { 571 boolean reportAll = relaxed || REPORT_ALL_REF_COMPARISONS; 572 573 WarningWithProperties best = null; 574 for (WarningWithProperties warn : warningList) { 575 if (best == null || warn.instance.getPriority() < best.instance.getPriority()) { 576 best = warn; 577 } 578 579 if (reportAll) { 580 if (relaxed) { 581 WarningPropertyUtil.addPropertiesForLocation( 583 warn.propertySet, 584 classContext, 585 method, 586 warn.location); 587 588 warn.propertySet.decorateBugInstance(warn.instance); 590 } 591 bugReporter.reportBug(warn.instance); 592 } 593 } 594 if (best != null && !reportAll) { 595 bugReporter.reportBug(best.instance); 596 } 597 } 598 599 private boolean isEqualsMethod(String methodName, String methodSig) { 600 return (methodName.equals("equals") && methodSig.equals("(Ljava/lang/Object;)Z")) 601 || (methodName.equals("equalIgnoreCases") && methodSig.equals("(Ljava/lang/String;)Z")); 602 } 603 604 private void checkRefComparison( 605 Location location, 606 JavaClass jclass, 607 MethodGen methodGen, 608 RefComparisonTypeFrameModelingVisitor visitor, 609 TypeDataflow typeDataflow, 610 List<WarningWithProperties> stringComparisonList, 611 List<WarningWithProperties> refComparisonList) throws DataflowAnalysisException { 612 613 InstructionHandle handle = location.getHandle(); 614 615 TypeFrame frame = typeDataflow.getFactAtLocation(location); 616 if (frame.getStackDepth() < 2) 617 throw new DataflowAnalysisException("Stack underflow", methodGen, handle); 618 619 int numSlots = frame.getNumSlots(); 620 Type lhsType = frame.getValue(numSlots - 1); 621 Type rhsType = frame.getValue(numSlots - 2); 622 623 if (lhsType instanceof ReferenceType && rhsType instanceof ReferenceType) { 624 String lhs = SignatureConverter.convert(lhsType.getSignature()); 625 String rhs = SignatureConverter.convert(rhsType.getSignature()); 626 627 if (!lhs.equals(rhs)) 628 return; 629 630 if (lhs.equals("java.lang.String")) { 631 handleStringComparison(jclass, methodGen, visitor, stringComparisonList, location, lhsType, rhsType); 632 } else if (suspiciousSet.contains(lhs)) { 633 handleSuspiciousRefComparison(jclass, methodGen, refComparisonList, location, lhs); 634 } 635 } 636 } 637 638 private void handleStringComparison( 639 JavaClass jclass, 640 MethodGen methodGen, 641 RefComparisonTypeFrameModelingVisitor visitor, 642 List<WarningWithProperties> stringComparisonList, 643 Location location, 644 Type lhsType, 645 Type rhsType) { 646 if (DEBUG) System.out.println("String/String comparison at " + location.getHandle()); 647 648 byte type1 = lhsType.getType(); 655 byte type2 = rhsType.getType(); 656 657 String bugPattern = "ES_COMPARING_STRINGS_WITH_EQ"; 658 WarningPropertySet propertySet = new WarningPropertySet(); 665 if (type1 == T_STATIC_STRING && type2 == T_STATIC_STRING) { 666 propertySet.addProperty(RefComparisonWarningProperty.COMPARE_STATIC_STRINGS); 667 } else if (type1 == T_DYNAMIC_STRING || type2 == T_DYNAMIC_STRING) { 668 propertySet.addProperty(RefComparisonWarningProperty.DYNAMIC_AND_UNKNOWN); 669 } else if (type2 == T_PARAMETER_STRING || type1 == T_PARAMETER_STRING) { 670 bugPattern = "ES_COMPARING_PARAMETER_STRING_WITH_EQ"; 671 if (methodGen.isPublic() || methodGen.isProtected()) propertySet.addProperty(RefComparisonWarningProperty.STRING_PARAMETER_IN_PUBLIC_METHOD); 672 else propertySet.addProperty(RefComparisonWarningProperty.STRING_PARAMETER); 673 } else if (type1 == T_STATIC_STRING || type2 == T_STATIC_STRING) { 674 propertySet.addProperty(RefComparisonWarningProperty.STATIC_AND_UNKNOWN); 675 } else if (visitor.sawStringIntern()) { 676 propertySet.addProperty(RefComparisonWarningProperty.SAW_INTERN); 677 } 678 679 String sourceFile = jclass.getSourceFileName(); 680 BugInstance instance = 681 new BugInstance(this, bugPattern, BASE_ES_PRIORITY) 682 .addClassAndMethod(methodGen, sourceFile) 683 .addType("Ljava/lang/String;") 684 .addSourceLine(this.classContext, methodGen, sourceFile, location.getHandle()); 685 686 WarningWithProperties warn = new WarningWithProperties(instance, propertySet, location); 687 stringComparisonList.add(warn); 688 } 689 690 private void handleSuspiciousRefComparison( 691 JavaClass jclass, 692 MethodGen methodGen, 693 List<WarningWithProperties> refComparisonList, 694 Location location, 695 String lhs) { 696 String sourceFile = jclass.getSourceFileName(); 697 BugInstance instance = new BugInstance(this, "RC_REF_COMPARISON", lhs.equals("java.lang.Boolean") ? NORMAL_PRIORITY : HIGH_PRIORITY) 698 .addClassAndMethod(methodGen, sourceFile) 699 .addType("L" + lhs.replace('.', '/')+";") 700 .addSourceLine(this.classContext, methodGen, sourceFile, location.getHandle()); 701 702 refComparisonList.add(new WarningWithProperties(instance, new WarningPropertySet(), location)); 703 } 704 705 private static boolean testLikeName(String name) { 706 return name.toLowerCase().indexOf("test") >= 0; 707 } 708 private void checkEqualsComparison( 709 Location location, 710 JavaClass jclass, 711 MethodGen methodGen, 712 TypeDataflow typeDataflow) throws DataflowAnalysisException { 713 714 InstructionHandle handle = location.getHandle(); 715 String sourceFile = jclass.getSourceFileName(); 716 717 TypeFrame frame = typeDataflow.getFactAtLocation(location); 718 if (frame.getStackDepth() < 2) 719 throw new DataflowAnalysisException("Stack underflow", methodGen, handle); 720 721 int numSlots = frame.getNumSlots(); 722 Type lhsType_ = frame.getValue(numSlots - 2); 723 Type rhsType_ = frame.getValue(numSlots - 1); 724 725 726 if (lhsType_.getType() == T_TOP || lhsType_.getType() == T_BOTTOM 728 || rhsType_.getType() == T_TOP || rhsType_.getType() == T_BOTTOM) 729 return; 730 731 Method method = methodGen.getMethod(); 732 boolean looksLikeTestCase = method.getName().startsWith("test") && method.isPublic() && method.getSignature().equals("()V") 733 || testLikeName(jclass.getClassName())|| testLikeName(jclass.getSuperclassName()); 734 int priorityModifier = 0; 735 if (looksLikeTestCase) priorityModifier = 1; 736 if (methodGen.getName().startsWith("test") && methodGen.getSignature().equals("()V")) { 737 try { 738 if (jclass.getSuperclassName().equals("junit.framework.TestCase") || Hierarchy.isSubtype(methodGen.getClassName(), "junit.framework.TestCase")) 739 priorityModifier=2; 740 } catch (ClassNotFoundException e) { 741 AnalysisContext.reportMissingClass(e); 742 } 743 } 744 745 if (!(lhsType_ instanceof ReferenceType) || !(rhsType_ instanceof ReferenceType)) { 746 if (rhsType_.getType() == T_NULL) { 747 if (!looksLikeTestCase) 749 bugReporter.reportBug(new BugInstance(this, "EC_NULL_ARG", NORMAL_PRIORITY) 750 .addClassAndMethod(methodGen, sourceFile) 751 .addSourceLine(this.classContext, methodGen, sourceFile, location.getHandle())); 752 } else if (lhsType_.getType() == T_NULL) { 753 } else { 757 bugReporter.logError("equals() used to compare non-object type(s) " + 758 lhsType_ + " and " + rhsType_ + 759 " in " + 760 SignatureConverter.convertMethodSignature(methodGen) + 761 " at " + location.getHandle()); 762 } 763 return; 764 } 765 if (lhsType_ instanceof ArrayType && rhsType_ instanceof ArrayType) 766 bugReporter.reportBug(new BugInstance(this, "EC_BAD_ARRAY_COMPARE", NORMAL_PRIORITY) 767 .addClassAndMethod(methodGen, sourceFile) 768 .addType(lhsType_.getSignature()) 769 .addType(rhsType_.getSignature()) 770 .addSourceLine(this.classContext, methodGen, sourceFile, location.getHandle()) 771 ); 772 IncompatibleTypes result = IncompatibleTypes.getPriorityForAssumingCompatible(lhsType_, rhsType_); 773 if (result == IncompatibleTypes.ARRAY_AND_NON_ARRAY || result == IncompatibleTypes.ARRAY_AND_OBJECT) 774 bugReporter.reportBug(new BugInstance(this, "EC_ARRAY_AND_NONARRAY", result.getPriority()) 775 .addClassAndMethod(methodGen, sourceFile) 776 .addType(lhsType_.getSignature()) 777 .addType(rhsType_.getSignature()) 778 .addSourceLine(this.classContext, methodGen, sourceFile, location.getHandle()) 779 ); 780 else if (result == IncompatibleTypes.INCOMPATIBLE_CLASSES) { 781 String lhsSig = lhsType_.getSignature(); 782 String rhsSig = rhsType_.getSignature(); 783 boolean core = lhsSig.startsWith("Ljava") && rhsSig.startsWith("Ljava"); 784 if (core) { 785 looksLikeTestCase = false; 786 priorityModifier = 0; 787 } 788 if (!looksLikeTestCase) bugReporter.reportBug(new BugInstance(this, "EC_UNRELATED_TYPES", result.getPriority() + priorityModifier) 789 .addClassAndMethod(methodGen, sourceFile) 790 .addType(lhsSig) 791 .addType(rhsSig) 792 .addSourceLine(this.classContext, methodGen, sourceFile, location.getHandle()) 793 ); 794 } 795 else if (result == IncompatibleTypes.UNRELATED_CLASS_AND_INTERFACE) 796 bugReporter.reportBug(new BugInstance(this, "EC_UNRELATED_CLASS_AND_INTERFACE", result.getPriority()) 797 .addClassAndMethod(methodGen, sourceFile) 798 .addType(lhsType_.getSignature()) 799 .addType(rhsType_.getSignature()) 800 .addSourceLine(this.classContext, methodGen, sourceFile, location.getHandle()) 801 ); 802 else if (result == IncompatibleTypes.UNRELATED_INTERFACES) 803 bugReporter.reportBug(new BugInstance(this, "EC_UNRELATED_INTERFACES", result.getPriority()) 804 .addClassAndMethod(methodGen, sourceFile) 805 .addType(lhsType_.getSignature()) 806 .addType(rhsType_.getSignature()) 807 .addSourceLine(this.classContext, methodGen, sourceFile, location.getHandle()) 808 ); 809 } 810 811 public static void main(String [] argv) throws Exception { 812 if (argv.length != 1) { 813 System.err.println("Usage: " + FindRefComparison.class.getName() + " <class file>"); 814 System.exit(1); 815 } 816 817 DataflowTestDriver<TypeFrame, TypeAnalysis> driver = 818 new DataflowTestDriver<TypeFrame, TypeAnalysis>() { 819 @Override 820 public Dataflow<TypeFrame, TypeAnalysis> createDataflow(ClassContext classContext, Method method) 821 throws CFGBuilderException, DataflowAnalysisException { 822 823 RepositoryLookupFailureCallback lookupFailureCallback = 824 classContext.getLookupFailureCallback(); 825 MethodGen methodGen = classContext.getMethodGen(method); 826 if (methodGen == null) 827 throw new DataflowAnalysisException("Could not get methodGen for " + method.toString()); 828 DepthFirstSearch dfs = classContext.getDepthFirstSearch(method); 829 CFG cfg = classContext.getCFG(method); 830 ExceptionSetFactory exceptionSetFactory = classContext.getExceptionSetFactory(method); 831 832 TypeMerger typeMerger = 833 new RefComparisonTypeMerger(lookupFailureCallback, exceptionSetFactory); 834 TypeFrameModelingVisitor visitor = 835 new RefComparisonTypeFrameModelingVisitor(methodGen.getConstantPool(), lookupFailureCallback); 836 TypeAnalysis analysis = new TypeAnalysis(methodGen, cfg, dfs, typeMerger, visitor, 837 lookupFailureCallback, exceptionSetFactory); 838 Dataflow<TypeFrame, TypeAnalysis> dataflow = 839 new Dataflow<TypeFrame, TypeAnalysis>(cfg, analysis); 840 dataflow.execute(); 841 842 return dataflow; 843 } 844 }; 845 846 driver.execute(argv[0]); 847 } 848 849 850 851 public void report() { 852 } 854 } 855 856 | Popular Tags |