Program: 90945
Project: 90945
Buggy source:
/** 
 * This method performs a deep toString of the given Object. Primitive arrays are converted using their respective Arrays.toString methods while special handling is implemented for "container types", i.e. Object[], Map and Collection because those could contain themselves. <p/> dejaVu is used in case of those container types to prevent an endless recursion. <p/> It should be noted that neither AbstractMap.toString() nor AbstractCollection.toString() implement such a behavior. They only check if the container is directly contained in itself, but not if a contained container contains the original one. Because of that, Arrays.toString(Object[]) isn't safe either. Confusing? Just read the last paragraph again and check the respective toString() implementation. <p/> This means, in effect, that logging would produce a usable output even if an ordinary System.out.println(o) would produce a relatively hard-to-debug StackOverflowError.
 * @param o      the Object to convert into a String
 * @param str    the StringBuilder that o will be appended to
 * @param dejaVu a list of container identities that were already used.
 */
private static void recursiveDeepToString(Object o,StringBuilder str,Set dejaVu){
  if (o == null) {
    str.append("String_Node_Str");
    return;
  }
  if (o instanceof String) {
    str.append(o);
    return;
  }
  Class oClass=o.getClass();
  if (oClass.isArray()) {
    if (oClass == byte[].class) {
      str.append(Arrays.toString((byte[])o));
    }
 else     if (oClass == short[].class) {
      str.append(Arrays.toString((short[])o));
    }
 else     if (oClass == int[].class) {
      str.append(Arrays.toString((int[])o));
    }
 else     if (oClass == long[].class) {
      str.append(Arrays.toString((long[])o));
    }
 else     if (oClass == float[].class) {
      str.append(Arrays.toString((float[])o));
    }
 else     if (oClass == double[].class) {
      str.append(Arrays.toString((double[])o));
    }
 else     if (oClass == boolean[].class) {
      str.append(Arrays.toString((boolean[])o));
    }
 else     if (oClass == char[].class) {
      str.append(Arrays.toString((char[])o));
    }
 else {
      String id=identityToString(o);
      if (dejaVu.contains(id)) {
        str.append(RECURSION_PREFIX).append(id).append(RECURSION_SUFFIX);
      }
 else {
        dejaVu.add(id);
        Object[] oArray=(Object[])o;
        str.append("String_Node_Str");
        boolean first=true;
        for (int i=0; i < oArray.length; ++i) {
          Object current=oArray[i];
          if (first) {
            first=false;
          }
 else {
            str.append("String_Node_Str");
          }
          recursiveDeepToString(current,str,new HashSet(dejaVu));
        }
        str.append("String_Node_Str");
      }
    }
  }
 else   if (o instanceof Map) {
    String id=identityToString(o);
    if (dejaVu.contains(id)) {
      str.append(RECURSION_PREFIX).append(id).append(RECURSION_SUFFIX);
    }
 else {
      dejaVu.add(id);
      Map oMap=(Map)o;
      str.append("String_Node_Str");
      boolean isFirst=true;
      Iterator iter=oMap.entrySet().iterator();
      while (iter.hasNext()) {
        Map.Entry current=(Map.Entry)iter.next();
        if (isFirst) {
          isFirst=false;
        }
 else {
          str.append("String_Node_Str");
        }
        Object key=current.getKey();
        Object value=current.getValue();
        recursiveDeepToString(key,str,new HashSet(dejaVu));
        str.append("String_Node_Str");
        recursiveDeepToString(value,str,new HashSet(dejaVu));
      }
      str.append("String_Node_Str");
    }
  }
 else   if (o instanceof Collection) {
    String id=identityToString(o);
    if (dejaVu.contains(id)) {
      str.append(RECURSION_PREFIX).append(id).append(RECURSION_SUFFIX);
    }
 else {
      dejaVu.add(id);
      Collection oCol=(Collection)o;
      str.append("String_Node_Str");
      boolean isFirst=true;
      Iterator iter=oCol.iterator();
      while (iter.hasNext()) {
        Object current=iter.next();
        if (isFirst) {
          isFirst=false;
        }
 else {
          str.append("String_Node_Str");
        }
        recursiveDeepToString(current,str,new HashSet(dejaVu));
      }
      str.append("String_Node_Str");
    }
  }
 else   if (o instanceof Date) {
    Date date=(Date)o;
    SimpleDateFormat format=new SimpleDateFormat("String_Node_Str");
    str.append(format.format(date));
  }
 else {
    try {
      str.append(o.toString());
    }
 catch (    Throwable t) {
      str.append(ERROR_PREFIX);
      str.append(identityToString(o));
      str.append(ERROR_SEPARATOR);
      String msg=t.getMessage();
      String className=t.getClass().getName();
      str.append(className);
      if (!className.equals(msg)) {
        str.append(ERROR_MSG_SEPARATOR);
        str.append(msg);
      }
      str.append(ERROR_SUFFIX);
    }
  }
}

Fixed version (ground truth):
/** 
 * This method performs a deep toString of the given Object. Primitive arrays are converted using their respective Arrays.toString methods while special handling is implemented for "container types", i.e. Object[], Map and Collection because those could contain themselves. <p/> dejaVu is used in case of those container types to prevent an endless recursion. <p/> It should be noted that neither AbstractMap.toString() nor AbstractCollection.toString() implement such a behavior. They only check if the container is directly contained in itself, but not if a contained container contains the original one. Because of that, Arrays.toString(Object[]) isn't safe either. Confusing? Just read the last paragraph again and check the respective toString() implementation. <p/> This means, in effect, that logging would produce a usable output even if an ordinary System.out.println(o) would produce a relatively hard-to-debug StackOverflowError.
 * @param o      the Object to convert into a String
 * @param str    the StringBuilder that o will be appended to
 * @param dejaVu a list of container identities that were already used.
 */
private static void recursiveDeepToString(Object o,StringBuilder str,Set<String> dejaVu){
  if (o == null) {
    str.append("String_Node_Str");
    return;
  }
  if (o instanceof String) {
    str.append(o);
    return;
  }
  Class oClass=o.getClass();
  if (oClass.isArray()) {
    if (oClass == byte[].class) {
      str.append(Arrays.toString((byte[])o));
    }
 else     if (oClass == short[].class) {
      str.append(Arrays.toString((short[])o));
    }
 else     if (oClass == int[].class) {
      str.append(Arrays.toString((int[])o));
    }
 else     if (oClass == long[].class) {
      str.append(Arrays.toString((long[])o));
    }
 else     if (oClass == float[].class) {
      str.append(Arrays.toString((float[])o));
    }
 else     if (oClass == double[].class) {
      str.append(Arrays.toString((double[])o));
    }
 else     if (oClass == boolean[].class) {
      str.append(Arrays.toString((boolean[])o));
    }
 else     if (oClass == char[].class) {
      str.append(Arrays.toString((char[])o));
    }
 else {
      String id=identityToString(o);
      if (dejaVu.contains(id)) {
        str.append(RECURSION_PREFIX).append(id).append(RECURSION_SUFFIX);
      }
 else {
        dejaVu.add(id);
        Object[] oArray=(Object[])o;
        str.append("String_Node_Str");
        boolean first=true;
        for (        Object current : oArray) {
          if (first) {
            first=false;
          }
 else {
            str.append("String_Node_Str");
          }
          recursiveDeepToString(current,str,new HashSet<String>(dejaVu));
        }
        str.append("String_Node_Str");
      }
    }
  }
 else   if (o instanceof Map) {
    String id=identityToString(o);
    if (dejaVu.contains(id)) {
      str.append(RECURSION_PREFIX).append(id).append(RECURSION_SUFFIX);
    }
 else {
      dejaVu.add(id);
      Map oMap=(Map)o;
      str.append("String_Node_Str");
      boolean isFirst=true;
      for (      Object o1 : oMap.entrySet()) {
        Map.Entry current=(Map.Entry)o1;
        if (isFirst) {
          isFirst=false;
        }
 else {
          str.append("String_Node_Str");
        }
        Object key=current.getKey();
        Object value=current.getValue();
        recursiveDeepToString(key,str,new HashSet<String>(dejaVu));
        str.append("String_Node_Str");
        recursiveDeepToString(value,str,new HashSet<String>(dejaVu));
      }
      str.append("String_Node_Str");
    }
  }
 else   if (o instanceof Collection) {
    String id=identityToString(o);
    if (dejaVu.contains(id)) {
      str.append(RECURSION_PREFIX).append(id).append(RECURSION_SUFFIX);
    }
 else {
      dejaVu.add(id);
      Collection oCol=(Collection)o;
      str.append("String_Node_Str");
      boolean isFirst=true;
      for (      Object anOCol : oCol) {
        if (isFirst) {
          isFirst=false;
        }
 else {
          str.append("String_Node_Str");
        }
        recursiveDeepToString(anOCol,str,new HashSet<String>(dejaVu));
      }
      str.append("String_Node_Str");
    }
  }
 else   if (o instanceof Date) {
    Date date=(Date)o;
    SimpleDateFormat format=new SimpleDateFormat("String_Node_Str");
    str.append(format.format(date));
  }
 else {
    try {
      str.append(o.toString());
    }
 catch (    Throwable t) {
      str.append(ERROR_PREFIX);
      str.append(identityToString(o));
      str.append(ERROR_SEPARATOR);
      String msg=t.getMessage();
      String className=t.getClass().getName();
      str.append(className);
      if (!className.equals(msg)) {
        str.append(ERROR_MSG_SEPARATOR);
        str.append(msg);
      }
      str.append(ERROR_SUFFIX);
    }
  }
}