Program: 4452
Project: 4452
Buggy source:
/** 
 * Notification that a file has changed. This implementation is different than FileManager's in that it maintains the XML. Important note: This method is called AFTER the file has changed.  It is possible that the metadata we wanted to write did not get written out completely.  We should NOT attempt to add the old metadata again, because we may end up recursing infinitely trying to write this metadata. However, it isn't very robust to blindly assume that the only metadata associated with this file was audio metadata. So, we make use of the fact that addFileIfShared will only add one type of metadata per file.  We read the ID3 tags off the file and insert it first into the list, ensuring that the existing metadata is the one that's added, short-circuiting any infinite loops.
 */
public FileDesc fileChanged(File f){
  FileDesc fd=getFileDescForFile(f);
  if (fd == null)   return null;
  CreationTimeCache ctCache=CreationTimeCache.instance();
  Long cTime=ctCache.getCreationTime(fd.getSHA1Urn());
  List xmlDocs=new LinkedList();
  xmlDocs.addAll(fd.getLimeXMLDocuments());
  FileDesc removed=removeFileIfShared(f);
  Assert.that(fd == removed,"String_Node_Str");
  _needRebuild=true;
  fd=addFileIfShared(f,xmlDocs);
  if ((fd != null) && (cTime != null)) {
synchronized (ctCache) {
      ctCache.removeTime(fd.getSHA1Urn());
      ctCache.addTime(fd.getSHA1Urn(),cTime.longValue());
      ctCache.commitTime(fd.getSHA1Urn());
    }
  }
  return fd;
}

Fixed version (ground truth):
/** 
 * Notification that a file has changed. This implementation is different than FileManager's in that it maintains the XML. Important note: This method is called AFTER the file has changed.  It is possible that the metadata we wanted to write did not get written out completely.  We should NOT attempt to add the old metadata again, because we may end up recursing infinitely trying to write this metadata. However, it isn't very robust to blindly assume that the only metadata associated with this file was audio metadata. So, we make use of the fact that addFileIfShared will only add one type of metadata per file.  We read the ID3 tags off the file and insert it first into the list, ensuring that the existing metadata is the one that's added, short-circuiting any infinite loops.
 */
public FileDesc fileChanged(File f){
  FileDesc fd=getFileDescForFile(f);
  if (fd == null)   return null;
  CreationTimeCache ctCache=CreationTimeCache.instance();
  Long cTime=ctCache.getCreationTime(fd.getSHA1Urn());
  List xmlDocs=fd.getLimeXMLDocuments();
  if (LimeXMLUtils.isMP3File(f)) {
    try {
      LimeXMLDocument diskID3Doc=ID3Reader.readDocument(f);
      resolveAudioDocs(xmlDocs,diskID3Doc);
    }
 catch (    IOException e) {
      return super.fileChanged(f);
    }
  }
  FileDesc removed=removeFileIfShared(f);
  Assert.that(fd == removed,"String_Node_Str");
  _needRebuild=true;
  fd=addFileIfShared(f,xmlDocs);
  if ((fd != null) && (cTime != null)) {
synchronized (ctCache) {
      ctCache.removeTime(fd.getSHA1Urn());
      ctCache.addTime(fd.getSHA1Urn(),cTime.longValue());
      ctCache.commitTime(fd.getSHA1Urn());
    }
  }
  return fd;
}