Program: 59779
Project: 59779
Buggy source:
/** 
 * This gets really nasty now that constructors can invoke operations on us. The upshot is that we should check to see if instances have been registered by callees after each recursive invocation of injectFromPlan or constructor invocations. The error handling currently bails if the thing we just instantiated should be discarded. This could happen if (for instance), a constructor did a bindVolatileInstance of its own class to an instance, or somehow triggered an injection of itself with a different plan (an injection of itself with the same plan would lead to an infinite recursion, so it's not really our problem).
 * @param plan
 * @return
 * @throws InjectionException
 */
@SuppressWarnings("String_Node_Str") private <T>T injectFromPlan(InjectionPlan<T> plan) throws InjectionException {
  if (!plan.isFeasible()) {
    throw new InjectionException("String_Node_Str" + plan.getNode().getFullName() + "String_Node_Str"+ plan.toCantInjectString());
  }
  if (plan.isAmbiguous()) {
    throw new InjectionException("String_Node_Str" + plan.getNode().getFullName() + "String_Node_Str"+ plan.toCantInjectString());
  }
  if (plan.getNode() instanceof ClassNode) {
    T cached=getCachedInstance((ClassNode<T>)plan.getNode());
    if (cached != null) {
      return cached;
    }
  }
  if (plan instanceof InjectionFuturePlan) {
    InjectionFuturePlan<T> fut=(InjectionFuturePlan<T>)plan;
    final String key=fut.getNode().getFullName();
    try {
      InjectionFuture<?> ret=new InjectionFuture<>(this,javaNamespace.classForName(fut.getNode().getFullName()));
      pendingFutures.add(ret);
      return (T)ret;
    }
 catch (    ClassNotFoundException e) {
      throw new InjectionException("String_Node_Str" + key);
    }
  }
 else   if (plan instanceof JavaInstance) {
    return ((JavaInstance<T>)plan).instance;
  }
 else   if (plan instanceof Constructor) {
    final Constructor<T> constructor=(Constructor<T>)plan;
    final Object[] args=new Object[constructor.getArgs().length];
    final InjectionPlan<?>[] argPlans=constructor.getArgs();
    for (int i=0; i < argPlans.length; i++) {
      args[i]=injectFromPlan(argPlans[i]);
    }
    try {
      T ret;
      concurrentModificationGuard=true;
      try {
        ret=getConstructor((ConstructorDef<T>)constructor.getConstructorDef()).newInstance(args);
      }
 catch (      IllegalArgumentException e) {
        StringBuilder sb=new StringBuilder("String_Node_Str" + constructor.getConstructorDef() + "String_Node_Str");
        for (        Object o : args) {
          sb.append("String_Node_Str" + o);
        }
        sb.append("String_Node_Str");
        throw new IllegalStateException(sb.toString(),e);
      }
      if (ret instanceof ExternalConstructor) {
        ret=((ExternalConstructor<T>)ret).newInstance();
      }
      concurrentModificationGuard=false;
      instances.put(constructor.getNode(),ret);
      return ret;
    }
 catch (    ReflectiveOperationException e) {
      throw new InjectionException("String_Node_Str",e);
    }
  }
 else   if (plan instanceof Subplan) {
    Subplan<T> ambiguous=(Subplan<T>)plan;
    return injectFromPlan(ambiguous.getDelegatedPlan());
  }
 else   if (plan instanceof SetInjectionPlan) {
    SetInjectionPlan<T> setPlan=(SetInjectionPlan<T>)plan;
    Set<T> ret=new MonotonicHashSet<>();
    for (    InjectionPlan<T> subplan : setPlan.getEntryPlans()) {
      ret.add(injectFromPlan(subplan));
    }
    return (T)ret;
  }
 else {
    throw new IllegalStateException("String_Node_Str" + plan);
  }
}

Fixed version (ground truth):
/** 
 * This gets really nasty now that constructors can invoke operations on us. The upshot is that we should check to see if instances have been registered by callees after each recursive invocation of injectFromPlan or constructor invocations. The error handling currently bails if the thing we just instantiated should be discarded. This could happen if (for instance), a constructor did a bindVolatileInstance of its own class to an instance, or somehow triggered an injection of itself with a different plan (an injection of itself with the same plan would lead to an infinite recursion, so it's not really our problem).
 * @param plan
 * @return
 * @throws InjectionException
 */
@SuppressWarnings("String_Node_Str") private <T>T injectFromPlan(InjectionPlan<T> plan) throws InjectionException {
  if (!plan.isFeasible()) {
    throw new InjectionException("String_Node_Str" + plan.getNode().getFullName() + "String_Node_Str"+ plan.toCantInjectString());
  }
  if (plan.isAmbiguous()) {
    throw new InjectionException("String_Node_Str" + plan.getNode().getFullName() + "String_Node_Str"+ plan.toCantInjectString());
  }
  if (plan instanceof InjectionFuturePlan) {
    InjectionFuturePlan<T> fut=(InjectionFuturePlan<T>)plan;
    final String key=fut.getNode().getFullName();
    try {
      InjectionFuture<?> ret=new InjectionFuture<>(this,javaNamespace.classForName(fut.getNode().getFullName()));
      pendingFutures.add(ret);
      return (T)ret;
    }
 catch (    ClassNotFoundException e) {
      throw new InjectionException("String_Node_Str" + key);
    }
  }
 else   if (plan.getNode() instanceof ClassNode && null != getCachedInstance((ClassNode<T>)plan.getNode())) {
    return getCachedInstance((ClassNode<T>)plan.getNode());
  }
 else   if (plan instanceof JavaInstance) {
    return ((JavaInstance<T>)plan).instance;
  }
 else   if (plan instanceof Constructor) {
    final Constructor<T> constructor=(Constructor<T>)plan;
    final Object[] args=new Object[constructor.getArgs().length];
    final InjectionPlan<?>[] argPlans=constructor.getArgs();
    for (int i=0; i < argPlans.length; i++) {
      args[i]=injectFromPlan(argPlans[i]);
    }
    try {
      T ret;
      concurrentModificationGuard=true;
      try {
        ret=getConstructor((ConstructorDef<T>)constructor.getConstructorDef()).newInstance(args);
      }
 catch (      IllegalArgumentException e) {
        StringBuilder sb=new StringBuilder("String_Node_Str" + constructor.getConstructorDef() + "String_Node_Str");
        for (        Object o : args) {
          sb.append("String_Node_Str" + o);
        }
        sb.append("String_Node_Str");
        throw new IllegalStateException(sb.toString(),e);
      }
      if (ret instanceof ExternalConstructor) {
        ret=((ExternalConstructor<T>)ret).newInstance();
      }
      concurrentModificationGuard=false;
      instances.put(constructor.getNode(),ret);
      return ret;
    }
 catch (    ReflectiveOperationException e) {
      throw new InjectionException("String_Node_Str",e);
    }
  }
 else   if (plan instanceof Subplan) {
    Subplan<T> ambiguous=(Subplan<T>)plan;
    return injectFromPlan(ambiguous.getDelegatedPlan());
  }
 else   if (plan instanceof SetInjectionPlan) {
    SetInjectionPlan<T> setPlan=(SetInjectionPlan<T>)plan;
    Set<T> ret=new MonotonicHashSet<>();
    for (    InjectionPlan<T> subplan : setPlan.getEntryPlans()) {
      ret.add(injectFromPlan(subplan));
    }
    return (T)ret;
  }
 else {
    throw new IllegalStateException("String_Node_Str" + plan);
  }
}