Program: 42964
Project: 42964
Buggy source:
private Object clone(final Object orig,final boolean replace) throws IOException, ClassNotFoundException {
  if (orig == null) {
    return null;
  }
  final IdentityHashMap<Object,Object> clones=this.clones;
  Object cached=clones.get(orig);
  if (cached != null) {
    return cached;
  }
  final ClassCloner classCloner=this.classCloner;
  if (orig instanceof Class) {
    final Class<?> classObj=(Class<?>)orig;
    final Class<?> clonedClass=Proxy.isProxyClass(classObj) ? classCloner.cloneProxy(classObj) : classCloner.clone(classObj);
    clones.put(orig,clonedClass);
    return clonedClass;
  }
  if ((cached=delegate.clone(orig,this,classCloner)) != null) {
    clones.put(orig,cached);
    return cached;
  }
  final Class<? extends Object> objClass=orig.getClass();
  if (orig instanceof Enum) {
    @SuppressWarnings("String_Node_Str") final Class<? extends Enum> cloneClass=((Class<?>)clone(objClass)).asSubclass(Enum.class);
    if (cloneClass == objClass) {
      return orig;
    }
 else {
      @SuppressWarnings("String_Node_Str") final Class<? extends Enum> cloneEnumClass;
      final Class<?> enumClass=((Enum<?>)orig).getDeclaringClass();
      if (enumClass == objClass) {
        cloneEnumClass=cloneClass;
      }
 else {
        cloneEnumClass=((Class<?>)clone(enumClass)).asSubclass(Enum.class);
      }
      return Enum.valueOf(cloneEnumClass,((Enum<?>)orig).name());
    }
  }
  final Class<?> clonedClass=(Class<?>)clone(objClass);
  if (Proxy.isProxyClass(objClass)) {
    return Proxy.newProxyInstance(clonedClass.getClassLoader(),clonedClass.getInterfaces(),(InvocationHandler)clone(getInvocationHandler(orig)));
  }
  if (UNCLONED.contains(objClass)) {
    return orig;
  }
  if (objClass.isArray()) {
    Object simpleClone=simpleClone(orig,objClass);
    if (simpleClone != null)     return simpleClone;
    final Object[] origArray=(Object[])orig;
    final int len=origArray.length;
    final boolean sameClass=objClass == clonedClass;
    if (sameClass && len == 0) {
      clones.put(orig,orig);
      return orig;
    }
    if (UNCLONED.contains(objClass.getComponentType())) {
      final Object[] clone=origArray.clone();
      clones.put(orig,clone);
      return clone;
    }
    final Object[] clone;
    if (sameClass) {
      clone=origArray.clone();
    }
 else {
      clone=(Object[])Array.newInstance(clonedClass.getComponentType(),len);
    }
    clones.put(orig,clone);
    for (int i=0; i < len; i++) {
      clone[i]=clone(origArray[i]);
    }
    return clone;
  }
  final SerializableClass info=registry.lookup(objClass);
  if (replace) {
    Object replaced=orig;
    if (info.hasWriteReplace()) {
      replaced=info.callWriteReplace(replaced);
    }
    replaced=objectResolver.writeReplace(replaced);
    if (replaced != orig) {
      Object clone=clone(replaced,false);
      clones.put(orig,clone);
      return clone;
    }
  }
  final Object clone;
  if (orig instanceof Externalizable) {
    final Externalizable externalizable=(Externalizable)orig;
    clone=externalizedCreator.create((Class<?>)clone(objClass));
    clones.put(orig,clone);
    final Queue<Step> steps=new ArrayDeque<Step>();
    externalizable.writeExternal(new StepObjectOutput(steps));
    ((Externalizable)clone).readExternal(new StepObjectInput(steps));
  }
 else   if (serializabilityChecker.isSerializable(objClass)) {
    clone=serializedCreator.create((Class<?>)clone(objClass));
    final Class<?> cloneClass=clone.getClass();
    if (!(serializabilityChecker.isSerializable(cloneClass))) {
      throw new NotSerializableException(cloneClass.getName());
    }
    clones.put(orig,clone);
    initSerializableClone(orig,info,clone,cloneClass);
  }
 else {
    throw new NotSerializableException(objClass.getName());
  }
  Object replaced=clone;
  if (info.hasReadResolve()) {
    replaced=info.callReadResolve(replaced);
  }
  replaced=objectResolver.readResolve(replaced);
  if (replaced != clone)   clones.put(orig,replaced);
  return replaced;
}

Fixed version (ground truth):
private Object clone(final Object orig,final boolean replace) throws IOException, ClassNotFoundException {
  if (orig == null) {
    return null;
  }
  final IdentityHashMap<Object,Object> clones=this.clones;
  Object cached=clones.get(orig);
  if (cached != null) {
    return cached;
  }
  final ClassCloner classCloner=this.classCloner;
  if (orig instanceof Class) {
    final Class<?> classObj=(Class<?>)orig;
    final Class<?> clonedClass=Proxy.isProxyClass(classObj) ? classCloner.cloneProxy(classObj) : classCloner.clone(classObj);
    clones.put(orig,clonedClass);
    return clonedClass;
  }
  if ((cached=delegate.clone(orig,this,classCloner)) != null) {
    clones.put(orig,cached);
    return cached;
  }
  final Class<? extends Object> objClass=orig.getClass();
  if (orig instanceof Enum) {
    @SuppressWarnings("String_Node_Str") final Class<? extends Enum> cloneClass=((Class<?>)clone(objClass)).asSubclass(Enum.class);
    if (cloneClass == objClass) {
      return orig;
    }
 else {
      @SuppressWarnings("String_Node_Str") final Class<? extends Enum> cloneEnumClass;
      final Class<?> enumClass=((Enum<?>)orig).getDeclaringClass();
      if (enumClass == objClass) {
        cloneEnumClass=cloneClass;
      }
 else {
        cloneEnumClass=((Class<?>)clone(enumClass)).asSubclass(Enum.class);
      }
      return Enum.valueOf(cloneEnumClass,((Enum<?>)orig).name());
    }
  }
  final Class<?> clonedClass=(Class<?>)clone(objClass);
  if (Proxy.isProxyClass(objClass)) {
    return Proxy.newProxyInstance(clonedClass.getClassLoader(),clonedClass.getInterfaces(),(InvocationHandler)clone(getInvocationHandler(orig)));
  }
  if (UNCLONED.contains(objClass)) {
    return orig;
  }
  if (objClass.isArray()) {
    Object simpleClone=simpleClone(orig,objClass);
    if (simpleClone != null)     return simpleClone;
    final Object[] origArray=(Object[])orig;
    final int len=origArray.length;
    final boolean sameClass=objClass == clonedClass;
    if (sameClass && len == 0) {
      clones.put(orig,orig);
      return orig;
    }
    if (UNCLONED.contains(objClass.getComponentType())) {
      final Object[] clone=origArray.clone();
      clones.put(orig,clone);
      return clone;
    }
    final Object[] clone;
    if (sameClass) {
      clone=origArray.clone();
    }
 else {
      clone=(Object[])Array.newInstance(clonedClass.getComponentType(),len);
    }
    clones.put(orig,clone);
    for (int i=0; i < len; i++) {
      clone[i]=clone(origArray[i]);
    }
    return clone;
  }
  final SerializableClass info=registry.lookup(objClass);
  if (replace) {
    Object replaced=orig;
    if (info.hasWriteReplace()) {
      replaced=info.callWriteReplace(replaced);
    }
    replaced=objectResolver.writeReplace(replaced);
    if (replaced != orig) {
      Object clone=clone(replaced,false);
      clones.put(orig,clone);
      return clone;
    }
  }
  final Object clone;
  if (orig instanceof Externalizable) {
    final Externalizable externalizable=(Externalizable)orig;
    clone=externalizedCreator.create((Class<?>)clone(objClass));
    clones.put(orig,clone);
    final Queue<Step> steps=new ArrayDeque<Step>();
    final StepObjectOutput soo=new StepObjectOutput(steps);
    externalizable.writeExternal(soo);
    soo.doFinish();
    ((Externalizable)clone).readExternal(new StepObjectInput(steps));
  }
 else   if (serializabilityChecker.isSerializable(objClass)) {
    clone=serializedCreator.create((Class<?>)clone(objClass));
    final Class<?> cloneClass=clone.getClass();
    if (!(serializabilityChecker.isSerializable(cloneClass))) {
      throw new NotSerializableException(cloneClass.getName());
    }
    clones.put(orig,clone);
    initSerializableClone(orig,info,clone,cloneClass);
  }
 else {
    throw new NotSerializableException(objClass.getName());
  }
  Object replaced=clone;
  if (info.hasReadResolve()) {
    replaced=info.callReadResolve(replaced);
  }
  replaced=objectResolver.readResolve(replaced);
  if (replaced != clone)   clones.put(orig,replaced);
  return replaced;
}