Program: 44160
Project: 44160
Buggy source:
/** 
 * Dumps the given object as JSON representation followed by a separator into the given StreamBuilder.
 * @param out StreamBuilder
 * @param o object
 * @param separator separator character to append after the object or<code>'\0'</code> to append no separator.
 */
private void dumpObject(JSONCharacterSink out,Object o,char separator,Collection<String> ignoredProps){
  if (o == null) {
    out.append("String_Node_Str");
  }
 else {
    Class oClass=o.getClass();
    JSONifier jsonifier;
    TypeConverter typeConverterFromClass=null;
    if (oClass.isPrimitive()) {
      out.append(o);
    }
 else     if (Number.class.isAssignableFrom(oClass) || oClass.equals(Boolean.class) || oClass.equals(Character.class)) {
      out.append(o);
    }
 else     if (o instanceof String) {
      quote(out,(String)o);
    }
 else     if (o instanceof Collection) {
      out.append('[');
      for (Iterator i=((Collection)o).iterator(); i.hasNext(); ) {
        dumpObject(out,i.next(),i.hasNext() ? ',' : '\0',ignoredProps);
      }
      out.append(']');
    }
 else     if (o.getClass().isArray()) {
      out.append('[');
      int len=Array.getLength(o);
      for (int i=0; i < len; i++) {
        dumpObject(out,Array.get(o,i),((i < (len - 1)) ? ',' : '\0'),ignoredProps);
      }
      out.append(']');
    }
 else     if (o instanceof Map) {
      out.append('{');
      Map m=(Map)o;
      for (Iterator i=m.keySet().iterator(); i.hasNext(); ) {
        Object key=i.next();
        dumpObject(out,key.toString(),'\0',ignoredProps);
        out.append(':');
        dumpObject(out,m.get(key),i.hasNext() ? ',' : '\0',ignoredProps);
      }
      out.append('}');
    }
 else     if ((jsonifier=getJSONifierForClass(oClass)) != null) {
      if (jsonifier instanceof SinkAwareJSONifier) {
        ((SinkAwareJSONifier)jsonifier).writeToSink(out,o);
      }
 else {
        out.append(jsonifier.toJSON(o));
      }
    }
 else     if (o instanceof JSONable) {
      out.append(((JSONable)o).toJSON());
    }
 else     if (o instanceof Class) {
      quote(out,((Class)o).getName());
    }
 else     if (o instanceof Enum) {
      quote(out,((Enum)o).name());
    }
 else     if (typeConvertersByClass != null && (typeConverterFromClass=typeConvertersByClass.get(o.getClass())) != null) {
      Object value=typeConverterFromClass.toJSON(o);
      dumpObject(out,value,'\0',ignoredProps);
    }
 else {
      BeanInfo info;
      try {
        info=Introspector.getBeanInfo(o.getClass());
      }
 catch (      IntrospectionException e) {
        throw ExceptionWrapper.wrap(e);
      }
      out.append('{');
      boolean first=true;
      PropertyDescriptor[] pds=info.getPropertyDescriptors();
      for (int cp=0; cp < pds.length; cp++) {
        try {
          PropertyDescriptor pd=pds[cp];
          Method method=pd.getReadMethod();
          Method writeMethod=pd.getWriteMethod();
          if (method != null) {
            Object value=method.invoke(o,(Object[])null);
            if (typeConverterCache != null) {
              TypeConverter typeConverter=typeConverterCache.getTypeConverter(o,pd.getName());
              if (typeConverter != null) {
                value=typeConverter.toJSON(value);
              }
            }
            String name=pd.getName();
            boolean ignore=(ignoredProps != null && ignoredProps.contains(name));
            if (!name.equals("String_Node_Str") && !ignore) {
              JSONProperty jsonProperty=method.getAnnotation(JSONProperty.class);
              if (jsonProperty == null && writeMethod != null) {
                jsonProperty=writeMethod.getAnnotation(JSONProperty.class);
              }
              if (jsonProperty != null) {
                String nameFromAnnotation=jsonProperty.value();
                if (nameFromAnnotation.length() > 0) {
                  name=jsonProperty.value();
                }
                ignore=jsonProperty.ignore() || (value == null && jsonProperty.ignoreIfNull());
              }
              if (!ignore) {
                if (!first) {
                  out.append(',');
                }
                quote(out,name);
                out.append(':');
                dumpObject(out,value,'\0',ignoredProps);
                first=false;
              }
            }
          }
        }
 catch (        IllegalAccessException e) {
          throw ExceptionWrapper.wrap(e);
        }
catch (        InvocationTargetException e) {
          throw ExceptionWrapper.wrap(e);
        }
      }
      if (o instanceof DynamicProperties) {
        DynamicProperties dynAttrs=(DynamicProperties)o;
        for (        String name : dynAttrs.propertyNames()) {
          if (!first) {
            out.append(',');
          }
          first=false;
          quote(out,name);
          out.append(':');
          dumpObject(out,dynAttrs.getProperty(name),'\0',ignoredProps);
        }
      }
      out.append('}');
    }
  }
  if (separator != '\0') {
    out.append(separator);
  }
}

Fixed version (ground truth):
/** 
 * Dumps the given object as JSON representation followed by a separator into the given StreamBuilder.
 * @param out StreamBuilder
 * @param o object
 * @param separator separator character to append after the object or<code>'\0'</code> to append no separator.
 */
private void dumpObject(JSONCharacterSink out,Object o,char separator,Collection<String> ignoredProps){
  if (o == null) {
    out.append("String_Node_Str");
  }
 else {
    Class oClass=o.getClass();
    JSONifier jsonifier;
    TypeConverter typeConverterFromClass=null;
    if (oClass.isPrimitive()) {
      out.append(o);
    }
 else     if (Number.class.isAssignableFrom(oClass) || oClass.equals(Boolean.class) || oClass.equals(Character.class)) {
      out.append(o);
    }
 else     if (o instanceof String) {
      quote(out,(String)o);
    }
 else     if (o instanceof Collection) {
      out.append('[');
      for (Iterator i=((Collection)o).iterator(); i.hasNext(); ) {
        dumpObject(out,i.next(),i.hasNext() ? ',' : '\0',ignoredProps);
      }
      out.append(']');
    }
 else     if (o.getClass().isArray()) {
      out.append('[');
      int len=Array.getLength(o);
      for (int i=0; i < len; i++) {
        dumpObject(out,Array.get(o,i),((i < (len - 1)) ? ',' : '\0'),ignoredProps);
      }
      out.append(']');
    }
 else     if (o instanceof Map) {
      out.append('{');
      Map m=(Map)o;
      for (Iterator i=m.keySet().iterator(); i.hasNext(); ) {
        Object key=i.next();
        dumpObject(out,key.toString(),'\0',ignoredProps);
        out.append(':');
        dumpObject(out,m.get(key),i.hasNext() ? ',' : '\0',ignoredProps);
      }
      out.append('}');
    }
 else     if ((jsonifier=getJSONifierForClass(oClass)) != null) {
      if (jsonifier instanceof SinkAwareJSONifier) {
        ((SinkAwareJSONifier)jsonifier).writeToSink(out,o);
      }
 else {
        out.append(jsonifier.toJSON(o));
      }
    }
 else     if (o instanceof JSONable) {
      out.append(((JSONable)o).toJSON());
    }
 else     if (o instanceof Class) {
      quote(out,((Class)o).getName());
    }
 else     if (o instanceof Enum) {
      quote(out,((Enum)o).name());
    }
 else     if (typeConvertersByClass != null && (typeConverterFromClass=typeConvertersByClass.get(o.getClass())) != null) {
      Object value=typeConverterFromClass.toJSON(o);
      dumpObject(out,value,'\0',ignoredProps);
    }
 else {
      BeanInfo info;
      try {
        info=Introspector.getBeanInfo(o.getClass());
      }
 catch (      IntrospectionException e) {
        throw ExceptionWrapper.wrap(e);
      }
      out.append('{');
      boolean first=true;
      PropertyDescriptor[] pds=info.getPropertyDescriptors();
      for (int cp=0; cp < pds.length; cp++) {
        try {
          PropertyDescriptor pd=pds[cp];
          Method method=pd.getReadMethod();
          Method writeMethod=pd.getWriteMethod();
          if (method != null) {
            String name=pd.getName();
            boolean ignore=(ignoredProps != null && ignoredProps.contains(name));
            if (!name.equals("String_Node_Str") && !ignore) {
              JSONProperty jsonProperty=method.getAnnotation(JSONProperty.class);
              if (jsonProperty == null && writeMethod != null) {
                jsonProperty=writeMethod.getAnnotation(JSONProperty.class);
              }
              if (jsonProperty != null) {
                String nameFromAnnotation=jsonProperty.value();
                if (nameFromAnnotation.length() > 0) {
                  name=jsonProperty.value();
                }
                ignore=jsonProperty.ignore();
              }
              Object value=null;
              if (!ignore) {
                value=method.invoke(o,(Object[])null);
              }
              if (value == null && jsonProperty.ignoreIfNull()) {
                ignore=true;
              }
              if (!ignore) {
                if (typeConverterCache != null) {
                  TypeConverter typeConverter=typeConverterCache.getTypeConverter(o,pd.getName());
                  if (typeConverter != null) {
                    value=typeConverter.toJSON(value);
                  }
                }
                if (!first) {
                  out.append(',');
                }
                quote(out,name);
                out.append(':');
                dumpObject(out,value,'\0',ignoredProps);
                first=false;
              }
            }
          }
        }
 catch (        IllegalAccessException e) {
          throw ExceptionWrapper.wrap(e);
        }
catch (        InvocationTargetException e) {
          throw ExceptionWrapper.wrap(e);
        }
      }
      if (o instanceof DynamicProperties) {
        DynamicProperties dynAttrs=(DynamicProperties)o;
        for (        String name : dynAttrs.propertyNames()) {
          if (!first) {
            out.append(',');
          }
          first=false;
          quote(out,name);
          out.append(':');
          dumpObject(out,dynAttrs.getProperty(name),'\0',ignoredProps);
        }
      }
      out.append('}');
    }
  }
  if (separator != '\0') {
    out.append(separator);
  }
}