Program: 40565
Project: 40565
Buggy source:
/** 
 * Add any exceptional edges generated by the last instruction in a basic block.
 * @param last the last instruction in a basic block.
 */
private void addExceptionalEdges(Instruction last){
  IClassHierarchy cha=getMethod().getClassHierarchy();
  if (Exceptions.isPEI(last)) {
    Collection<TypeReference> exceptionTypes=null;
    boolean goToAllHandlers=false;
    ExceptionHandler[] hs=getExceptionHandlers();
    if (last.getOpcode() == OP_athrow) {
      goToAllHandlers=true;
    }
 else {
      if (hs != null && hs.length > 0) {
        exceptionTypes=Exceptions.getExceptionTypes(getMethod().getDeclaringClass().getReference().getClassLoader(),last,cha);
      }
    }
    if (hs != null && hs.length > 0) {
      if (!goToAllHandlers) {
        exceptionTypes=HashSetFactory.make(exceptionTypes);
      }
      for (int j=0; j < hs.length; j++) {
        if (DEBUG) {
          System.err.println("String_Node_Str" + hs[j]);
        }
        BasicBlock b=getBlockForInstruction(hs[j].getHandler());
        if (DEBUG) {
          System.err.println("String_Node_Str" + b);
        }
        if (goToAllHandlers) {
          addExceptionalEdgeTo(b);
        }
 else {
          TypeReference caughtException=null;
          if (hs[j].getCatchClass() != null) {
            ClassLoaderReference loader=ShrikeCFG.this.getMethod().getDeclaringClass().getReference().getClassLoader();
            caughtException=ShrikeUtil.makeTypeReference(loader,hs[j].getCatchClass());
            IClass caughtClass=cha.lookupClass(caughtException);
            if (caughtClass == null) {
              addExceptionalEdgeTo(b);
              Warnings.add(FailedExceptionResolutionWarning.create(caughtException));
              caughtException=null;
            }
 else {
              addExceptionalEdgeTo(b);
              exceptionTypes.clear();
            }
          }
          if (caughtException != null) {
            HashSet<TypeReference> caught=HashSetFactory.make(exceptionTypes.size());
            for (Iterator it=exceptionTypes.iterator(); it.hasNext(); ) {
              TypeReference t=(TypeReference)it.next();
              if (t != null) {
                IClass klass=cha.lookupClass(t);
                if (klass == null) {
                  Warnings.add(FailedExceptionResolutionWarning.create(caughtException));
                  addExceptionalEdgeTo(b);
                }
 else {
                  IClass caughtClass=cha.lookupClass(caughtException);
                  if (cha.isSubclassOf(klass,caughtClass) || cha.isSubclassOf(caughtClass,klass)) {
                    addExceptionalEdgeTo(b);
                    if (cha.isSubclassOf(klass,caughtClass)) {
                      caught.add(t);
                    }
                  }
                }
              }
            }
            exceptionTypes.removeAll(caught);
          }
        }
      }
      if (exceptionTypes == null || !exceptionTypes.isEmpty()) {
        BasicBlock exit=exit();
        addExceptionalEdgeTo(exit);
      }
    }
 else {
      BasicBlock exit=exit();
      addExceptionalEdgeTo(exit);
    }
  }
}

Fixed version (ground truth):
/** 
 * Add any exceptional edges generated by the last instruction in a basic block.
 * @param last the last instruction in a basic block.
 */
private void addExceptionalEdges(Instruction last){
  IClassHierarchy cha=getMethod().getClassHierarchy();
  if (Exceptions.isPEI(last)) {
    Collection<TypeReference> exceptionTypes=null;
    boolean goToAllHandlers=false;
    ExceptionHandler[] hs=getExceptionHandlers();
    if (last.getOpcode() == OP_athrow) {
      goToAllHandlers=true;
    }
 else {
      if (hs != null && hs.length > 0) {
        exceptionTypes=Exceptions.getExceptionTypes(getMethod().getDeclaringClass().getReference().getClassLoader(),last,cha);
      }
    }
    if (hs != null && hs.length > 0) {
      if (!goToAllHandlers) {
        exceptionTypes=HashSetFactory.make(exceptionTypes);
      }
      for (int j=0; j < hs.length; j++) {
        if (DEBUG) {
          System.err.println("String_Node_Str" + hs[j]);
        }
        BasicBlock b=getBlockForInstruction(hs[j].getHandler());
        if (DEBUG) {
          System.err.println("String_Node_Str" + b);
        }
        if (goToAllHandlers) {
          addExceptionalEdgeTo(b);
        }
 else {
          TypeReference caughtException=null;
          if (hs[j].getCatchClass() != null) {
            ClassLoaderReference loader=ShrikeCFG.this.getMethod().getDeclaringClass().getReference().getClassLoader();
            caughtException=ShrikeUtil.makeTypeReference(loader,hs[j].getCatchClass());
            if (DEBUG) {
              System.err.println("String_Node_Str" + caughtException);
            }
            IClass caughtClass=cha.lookupClass(caughtException);
            if (caughtClass == null) {
              addExceptionalEdgeTo(b);
              Warnings.add(FailedExceptionResolutionWarning.create(caughtException));
              caughtException=null;
            }
          }
 else {
            addExceptionalEdgeTo(b);
            exceptionTypes.clear();
            caughtException=null;
          }
          if (caughtException != null) {
            HashSet<TypeReference> caught=HashSetFactory.make(exceptionTypes.size());
            for (Iterator it=exceptionTypes.iterator(); it.hasNext(); ) {
              TypeReference t=(TypeReference)it.next();
              if (t != null) {
                IClass klass=cha.lookupClass(t);
                if (klass == null) {
                  Warnings.add(FailedExceptionResolutionWarning.create(caughtException));
                  addExceptionalEdgeTo(b);
                }
 else {
                  IClass caughtClass=cha.lookupClass(caughtException);
                  if (cha.isSubclassOf(klass,caughtClass) || cha.isSubclassOf(caughtClass,klass)) {
                    addExceptionalEdgeTo(b);
                    if (cha.isSubclassOf(klass,caughtClass)) {
                      caught.add(t);
                    }
                  }
                }
              }
            }
            exceptionTypes.removeAll(caught);
          }
        }
      }
      if (exceptionTypes == null || !exceptionTypes.isEmpty()) {
        BasicBlock exit=exit();
        addExceptionalEdgeTo(exit);
      }
    }
 else {
      BasicBlock exit=exit();
      addExceptionalEdgeTo(exit);
    }
  }
}