Program: 105654
Project: 105654
Buggy source:
/** 
 * From a list of files (each being one part of the multipart upload), concatentate all files into a single object that can be accessed by normal S3 calls.  This function could take a long time since a multipart is allowed to have upto 10,000 parts (each 5 gib long).   Amazon defines that while this operation is in progress whitespace is sent back to the client inorder to keep the HTTP connection alive.
 * @param mountedRoot - where both the source and dest buckets are located
 * @param destBucket - resulting location of the concatenated objects
 * @param fileName - resulting file name of the concatenated objects
 * @param sourceBucket - special bucket used to save uploaded file parts
 * @param parts - an array of file names in the sourceBucket
 * @param client - if not null, then keep the servlet connection alive while this potentially long concatentation takes place
 * @return OrderedPair with the first value the MD5 of the final object, and the second value the length of the final object
 */
@Override public OrderedPair<String,Long> concatentateObjects(String mountedRoot,String destBucket,String fileName,String sourceBucket,S3MultipartPart[] parts,OutputStream client){
  MessageDigest md5;
  long totalLength=0;
  try {
    md5=MessageDigest.getInstance("String_Node_Str");
  }
 catch (  NoSuchAlgorithmException e) {
    logger.error("String_Node_Str" + e.getMessage(),e);
    throw new InternalErrorException("String_Node_Str",e);
  }
  File file=new File(getBucketFolderDir(mountedRoot,destBucket) + File.separatorChar + fileName);
  try {
    file.delete();
    file.createNewFile();
    final FileOutputStream fos=new FileOutputStream(file);
    byte[] buffer=new byte[4096];
    for (int i=0; i < parts.length; i++) {
      DataHandler nextPart=loadObject(mountedRoot,sourceBucket,parts[i].getPath());
      InputStream is=nextPart.getInputStream();
      int len=0;
      while ((len=is.read(buffer)) > 0) {
        fos.write(buffer,0,len);
        md5.update(buffer,0,len);
        totalLength+=len;
      }
      is.close();
      if (null != client) {
        client.write(new String("String_Node_Str").getBytes());
        client.flush();
      }
    }
    fos.close();
    return new OrderedPair<String,Long>(StringHelper.toHexString(md5.digest()),new Long(totalLength));
  }
 catch (  IOException e) {
    logger.error("String_Node_Str" + e.getMessage(),e);
    throw new OutOfStorageException(e);
  }
}

Fixed version (ground truth):
/** 
 * From a list of files (each being one part of the multipart upload), concatentate all files into a single object that can be accessed by normal S3 calls.  This function could take a long time since a multipart is allowed to have upto 10,000 parts (each 5 gib long).   Amazon defines that while this operation is in progress whitespace is sent back to the client inorder to keep the HTTP connection alive.
 * @param mountedRoot - where both the source and dest buckets are located
 * @param destBucket - resulting location of the concatenated objects
 * @param fileName - resulting file name of the concatenated objects
 * @param sourceBucket - special bucket used to save uploaded file parts
 * @param parts - an array of file names in the sourceBucket
 * @param client - if not null, then keep the servlet connection alive while this potentially long concatentation takes place
 * @return OrderedPair with the first value the MD5 of the final object, and the second value the length of the final object
 */
@Override public OrderedPair<String,Long> concatentateObjects(String mountedRoot,String destBucket,String fileName,String sourceBucket,S3MultipartPart[] parts,OutputStream client){
  MessageDigest md5;
  long totalLength=0;
  try {
    md5=MessageDigest.getInstance("String_Node_Str");
  }
 catch (  NoSuchAlgorithmException e) {
    logger.error("String_Node_Str" + e.getMessage(),e);
    throw new InternalErrorException("String_Node_Str",e);
  }
  File file=new File(getBucketFolderDir(mountedRoot,destBucket) + File.separatorChar + fileName);
  try {
    file.delete();
    file.createNewFile();
    try (final FileOutputStream fos=new FileOutputStream(file)){
      byte[] buffer=new byte[4096];
      for (int i=0; i < parts.length; i++) {
        DataHandler nextPart=loadObject(mountedRoot,sourceBucket,parts[i].getPath());
        InputStream is=nextPart.getInputStream();
        int len=0;
        while ((len=is.read(buffer)) > 0) {
          fos.write(buffer,0,len);
          md5.update(buffer,0,len);
          totalLength+=len;
        }
        is.close();
        if (null != client) {
          client.write(new String("String_Node_Str").getBytes());
          client.flush();
        }
      }
      return new OrderedPair<String,Long>(StringHelper.toHexString(md5.digest()),new Long(totalLength));
    }
 catch (    IOException e) {
      logger.error("String_Node_Str" + e.getMessage(),e);
      throw new OutOfStorageException(e);
    }
  }
 catch (  IOException e) {
    logger.error("String_Node_Str" + e.getMessage(),e);
    throw new OutOfStorageException(e);
  }
}