Program: 161829
Project: 161829
Buggy source:
/** 
 * Creates artificial annotations for non-overridden methods in subclasses. If the class A implements some method foo() which is marked as e.g. a source and class B extends A, but does not overwrite foo(), B.foo() must also be a source.
 * @param methods The list of method for which to create subclassannotations
 */
private void createSubclassAnnotations(final Set<AndroidMethod> methods){
  int copyCount=-1;
  int totalCopyCount=0;
  while (copyCount != 0)   copyCount=0;
  for (  AndroidMethod am : methods) {
    AbstractSootFeature asf=new AbstractSootFeature(ANDROID){
      @Override public Type appliesInternal(      AndroidMethod method){
        SootMethod parentMethod=getSootMethod(method);
        if (parentMethod == null)         return Type.NOT_SUPPORTED;
        boolean copied=false;
        if (!parentMethod.getDeclaringClass().getName().equals(method.getClassName())) {
          AndroidMethod parentMethodData=findAndroidMethod(parentMethod);
          if (parentMethodData == null)           return Type.NOT_SUPPORTED;
          if (parentMethodData.isAnnotated() && method.isAnnotated())           if (parentMethodData.isSource() != method.isSource() || parentMethodData.isSink() != method.isSink() || parentMethodData.isNeitherNor() != method.isNeitherNor())           throw new RuntimeException("String_Node_Str" + parentMethodData + "String_Node_Str"+ method);
          if (parentMethodData.getCategory() != null && method.getCategory() != null)           if (parentMethodData.getCategory() != method.getCategory())           throw new RuntimeException("String_Node_Str" + parentMethod + "String_Node_Str"+ method);
          if (parentMethodData.isAnnotated() && !method.isAnnotated()) {
            method.setSource(parentMethodData.isSource());
            method.setSink(parentMethodData.isSink());
            method.setNeitherNor(parentMethodData.isNeitherNor());
            copied=true;
          }
          if (parentMethodData.getCategory() != null && method.getCategory() == null)           method.setCategory(parentMethodData.getCategory());
          if (!parentMethodData.isAnnotated() && method.isAnnotated()) {
            parentMethodData.setSource(method.isSource());
            parentMethodData.setSink(method.isSink());
            parentMethodData.setNeitherNor(method.isNeitherNor());
            copied=true;
          }
          if (parentMethodData.getCategory() == null && method.getCategory() != null)           parentMethodData.setCategory(method.getCategory());
        }
        return copied ? Type.TRUE : Type.FALSE;
      }
      private AndroidMethod findAndroidMethod(      SootMethod sm){
        AndroidMethod smData=new AndroidMethod(sm);
        for (        AndroidMethod am : methods)         if (am.equals(smData))         return am;
        return null;
      }
    }
;
    if (asf.applies(am) == Type.TRUE) {
      copyCount++;
      totalCopyCount++;
    }
  }
  System.out.println("String_Node_Str" + totalCopyCount + "String_Node_Str");
}

Fixed version (ground truth):
/** 
 * Creates artificial annotations for non-overridden methods in subclasses. If the class A implements some method foo() which is marked as e.g. a source and class B extends A, but does not overwrite foo(), B.foo() must also be a source.
 * @param methods The list of method for which to create subclassannotations
 */
private void createSubclassAnnotations(final Set<AndroidMethod> methods){
  int copyCount=-1;
  int totalCopyCount=0;
  while (copyCount != 0) {
    copyCount=0;
    for (    AndroidMethod am : methods) {
      AbstractSootFeature asf=new AbstractSootFeature(ANDROID){
        @Override public Type appliesInternal(        AndroidMethod method){
          SootMethod parentMethod=getSootMethod(method);
          if (parentMethod == null)           return Type.NOT_SUPPORTED;
          boolean copied=false;
          if (!parentMethod.getDeclaringClass().getName().equals(method.getClassName())) {
            AndroidMethod parentMethodData=findAndroidMethod(parentMethod);
            if (parentMethodData == null)             return Type.NOT_SUPPORTED;
            if (parentMethodData.isAnnotated() && method.isAnnotated())             if (parentMethodData.isSource() != method.isSource() || parentMethodData.isSink() != method.isSink() || parentMethodData.isNeitherNor() != method.isNeitherNor())             throw new RuntimeException("String_Node_Str" + parentMethodData + "String_Node_Str"+ method);
            if (parentMethodData.getCategory() != null && method.getCategory() != null)             if (parentMethodData.getCategory() != method.getCategory())             throw new RuntimeException("String_Node_Str" + parentMethod + "String_Node_Str"+ method);
            if (parentMethodData.isAnnotated() && !method.isAnnotated()) {
              method.setSource(parentMethodData.isSource());
              method.setSink(parentMethodData.isSink());
              method.setNeitherNor(parentMethodData.isNeitherNor());
              copied=true;
            }
            if (parentMethodData.getCategory() != null && method.getCategory() == null)             method.setCategory(parentMethodData.getCategory());
            if (!parentMethodData.isAnnotated() && method.isAnnotated()) {
              parentMethodData.setSource(method.isSource());
              parentMethodData.setSink(method.isSink());
              parentMethodData.setNeitherNor(method.isNeitherNor());
              copied=true;
            }
            if (parentMethodData.getCategory() == null && method.getCategory() != null)             parentMethodData.setCategory(method.getCategory());
          }
          return copied ? Type.TRUE : Type.FALSE;
        }
        private AndroidMethod findAndroidMethod(        SootMethod sm){
          AndroidMethod smData=new AndroidMethod(sm);
          for (          AndroidMethod am : methods)           if (am.equals(smData))           return am;
          return null;
        }
      }
;
      if (asf.applies(am) == Type.TRUE) {
        copyCount++;
        totalCopyCount++;
      }
    }
  }
  System.out.println("String_Node_Str" + totalCopyCount + "String_Node_Str");
}