Program: 40341
Project: 40341
Buggy source:
/** 
 * Add any exceptional edges generated by the last instruction in a basic block.
 * @param last the last instruction in a basic block.
 */
protected void addExceptionalEdges(IInstruction last){
  IClassHierarchy cha=getMethod().getClassHierarchy();
  if (last.isPEI()) {
    Collection<TypeReference> exceptionTypes=null;
    boolean goToAllHandlers=false;
    ExceptionHandler[] hs=getExceptionHandlers();
    if (last instanceof ThrowInstruction) {
      goToAllHandlers=true;
    }
 else {
      if (hs != null && hs.length > 0) {
        IClassLoader loader=getMethod().getDeclaringClass().getClassLoader();
        BytecodeLanguage l=(BytecodeLanguage)loader.getLanguage();
        exceptionTypes=l.getImplicitExceptionTypes(last);
        if (last instanceof IInvokeInstruction) {
          IInvokeInstruction call=(IInvokeInstruction)last;
          exceptionTypes=HashSetFactory.make(exceptionTypes);
          MethodReference target=MethodReference.findOrCreate(l,loader.getReference(),call.getClassType(),call.getMethodName(),call.getMethodSignature());
          try {
            exceptionTypes.addAll(l.inferInvokeExceptions(target,cha));
          }
 catch (          InvalidClassFileException e) {
            e.printStackTrace();
            Assertions.UNREACHABLE();
          }
        }
      }
    }
    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) {
            IClass caughtClass=cha.lookupClass(caughtException);
            ArrayList<TypeReference> caught=new ArrayList<TypeReference>(exceptionTypes.size());
            for (            TypeReference t : exceptionTypes) {
              if (t != null) {
                IClass klass=cha.lookupClass(t);
                if (klass == null) {
                  Warnings.add(FailedExceptionResolutionWarning.create(caughtException));
                  addExceptionalEdgeTo(b);
                }
 else {
                  boolean subtype1=cha.isSubclassOf(klass,caughtClass);
                  if (subtype1 || cha.isSubclassOf(caughtClass,klass)) {
                    addExceptionalEdgeTo(b);
                    if (subtype1) {
                      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.
 */
protected void addExceptionalEdges(IInstruction last){
  IClassHierarchy cha=getMethod().getClassHierarchy();
  if (last.isPEI()) {
    Collection<TypeReference> exceptionTypes=null;
    boolean goToAllHandlers=false;
    ExceptionHandler[] hs=getExceptionHandlers();
    if (last instanceof ThrowInstruction) {
      goToAllHandlers=true;
    }
 else {
      if (hs != null && hs.length > 0) {
        IClassLoader loader=getMethod().getDeclaringClass().getClassLoader();
        BytecodeLanguage l=(BytecodeLanguage)loader.getLanguage();
        exceptionTypes=l.getImplicitExceptionTypes(last);
        if (last instanceof IInvokeInstruction) {
          IInvokeInstruction call=(IInvokeInstruction)last;
          exceptionTypes=HashSetFactory.make(exceptionTypes);
          MethodReference target=MethodReference.findOrCreate(l,loader.getReference(),call.getClassType(),call.getMethodName(),call.getMethodSignature());
          try {
            exceptionTypes.addAll(l.inferInvokeExceptions(target,cha));
          }
 catch (          InvalidClassFileException e) {
            e.printStackTrace();
            Assertions.UNREACHABLE();
          }
        }
      }
    }
    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) {
          if (DEBUG) {
            System.err.println("String_Node_Str" + b);
          }
          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 {
            if (DEBUG) {
              System.err.println("String_Node_Str");
            }
            if (!exceptionTypes.isEmpty()) {
              addExceptionalEdgeTo(b);
              exceptionTypes.clear();
              caughtException=null;
            }
          }
          if (caughtException != null) {
            IClass caughtClass=cha.lookupClass(caughtException);
            ArrayList<TypeReference> caught=new ArrayList<TypeReference>(exceptionTypes.size());
            for (            TypeReference t : exceptionTypes) {
              if (t != null) {
                IClass klass=cha.lookupClass(t);
                if (klass == null) {
                  Warnings.add(FailedExceptionResolutionWarning.create(caughtException));
                  addExceptionalEdgeTo(b);
                }
 else {
                  boolean subtype1=cha.isSubclassOf(klass,caughtClass);
                  if (subtype1 || cha.isSubclassOf(caughtClass,klass)) {
                    addExceptionalEdgeTo(b);
                    if (subtype1) {
                      caught.add(t);
                    }
                  }
                }
              }
            }
            exceptionTypes.removeAll(caught);
          }
        }
      }
      if (exceptionTypes == null || !exceptionTypes.isEmpty()) {
        BasicBlock exit=exit();
        addExceptionalEdgeTo(exit);
      }
    }
 else {
      BasicBlock exit=exit();
      addExceptionalEdgeTo(exit);
    }
  }
}