Program: 92937
Project: 92937
Buggy source:
/** 
 * Process one of the nested Tiff IFD directories. 2 bytes: number of tags for each tag 2 bytes: tag type 2 bytes: format code 4 bytes: component count
 */
private void processDirectory(Directory directory,HashSet<Integer> processedDirectoryOffsets,int dirStartOffset,int tiffHeaderOffset,final Metadata metadata){
  if (processedDirectoryOffsets.contains(new Integer(dirStartOffset)))   return;
  processedDirectoryOffsets.add(dirStartOffset);
  if (dirStartOffset >= _data.length || dirStartOffset < 0) {
    directory.addError("String_Node_Str");
    return;
  }
  if (!isDirectoryLengthValid(dirStartOffset,tiffHeaderOffset)) {
    directory.addError("String_Node_Str");
    return;
  }
  int dirTagCount=get16Bits(dirStartOffset);
  for (int tagNumber=0; tagNumber < dirTagCount; tagNumber++) {
    final int tagOffset=calculateTagOffset(dirStartOffset,tagNumber);
    final int tagType=get16Bits(tagOffset);
    final int formatCode=get16Bits(tagOffset + 2);
    if (formatCode < 1 || formatCode > MAX_FORMAT_CODE) {
      directory.addError("String_Node_Str" + formatCode);
      continue;
    }
    final int componentCount=get32Bits(tagOffset + 4);
    if (componentCount < 0) {
      directory.addError("String_Node_Str");
      continue;
    }
    final int byteCount=componentCount * BYTES_PER_FORMAT[formatCode];
    final int tagValueOffset=calculateTagValueOffset(byteCount,tagOffset,tiffHeaderOffset);
    if (tagValueOffset < 0 || tagValueOffset > _data.length) {
      directory.addError("String_Node_Str");
      continue;
    }
    if (byteCount < 0 || tagValueOffset + byteCount > _data.length) {
      directory.addError("String_Node_Str" + byteCount);
      continue;
    }
    final int subdirOffset=tiffHeaderOffset + get32Bits(tagValueOffset);
switch (tagType) {
case TAG_EXIF_OFFSET:
      processDirectory(metadata.getDirectory(ExifDirectory.class),processedDirectoryOffsets,subdirOffset,tiffHeaderOffset,metadata);
    continue;
case TAG_INTEROP_OFFSET:
  processDirectory(metadata.getDirectory(ExifInteropDirectory.class),processedDirectoryOffsets,subdirOffset,tiffHeaderOffset,metadata);
continue;
case TAG_GPS_INFO_OFFSET:
processDirectory(metadata.getDirectory(GpsDirectory.class),processedDirectoryOffsets,subdirOffset,tiffHeaderOffset,metadata);
continue;
case TAG_MAKER_NOTE:
processMakerNote(tagValueOffset,processedDirectoryOffsets,tiffHeaderOffset,metadata);
continue;
default :
processTag(directory,tagType,tagValueOffset,componentCount,formatCode);
break;
}
}
final int finalTagOffset=calculateTagOffset(dirStartOffset,dirTagCount);
int nextDirectoryOffset=get32Bits(finalTagOffset);
if (nextDirectoryOffset != 0) {
nextDirectoryOffset+=tiffHeaderOffset;
if (nextDirectoryOffset >= _data.length) {
return;
}
 else if (nextDirectoryOffset < dirStartOffset) {
return;
}
processDirectory(directory,processedDirectoryOffsets,nextDirectoryOffset,tiffHeaderOffset,metadata);
}
}

Fixed version (ground truth):
/** 
 * Process one of the nested Tiff IFD directories. 2 bytes: number of tags for each tag 2 bytes: tag type 2 bytes: format code 4 bytes: component count
 */
private void processDirectory(Directory directory,HashSet<Integer> processedDirectoryOffsets,int dirStartOffset,int tiffHeaderOffset,final Metadata metadata){
  if (processedDirectoryOffsets.contains(new Integer(dirStartOffset)))   return;
  processedDirectoryOffsets.add(dirStartOffset);
  if (dirStartOffset >= _data.length || dirStartOffset < 0) {
    directory.addError("String_Node_Str");
    return;
  }
  int dirTagCount=get16Bits(dirStartOffset);
  int dirLength=(2 + (12 * dirTagCount) + 4);
  if (dirLength + dirStartOffset > _data.length) {
    directory.addError("String_Node_Str");
    return;
  }
  for (int tagNumber=0; tagNumber < dirTagCount; tagNumber++) {
    final int tagOffset=calculateTagOffset(dirStartOffset,tagNumber);
    final int tagType=get16Bits(tagOffset);
    final int formatCode=get16Bits(tagOffset + 2);
    if (formatCode < 1 || formatCode > MAX_FORMAT_CODE) {
      directory.addError("String_Node_Str" + formatCode);
      continue;
    }
    final int componentCount=get32Bits(tagOffset + 4);
    if (componentCount < 0) {
      directory.addError("String_Node_Str");
      continue;
    }
    final int byteCount=componentCount * BYTES_PER_FORMAT[formatCode];
    final int tagValueOffset=calculateTagValueOffset(byteCount,tagOffset,tiffHeaderOffset);
    if (tagValueOffset < 0 || tagValueOffset > _data.length) {
      directory.addError("String_Node_Str");
      continue;
    }
    if (byteCount < 0 || tagValueOffset + byteCount > _data.length) {
      directory.addError("String_Node_Str" + byteCount);
      continue;
    }
    final int subdirOffset=tiffHeaderOffset + get32Bits(tagValueOffset);
switch (tagType) {
case TAG_EXIF_OFFSET:
      processDirectory(metadata.getDirectory(ExifDirectory.class),processedDirectoryOffsets,subdirOffset,tiffHeaderOffset,metadata);
    continue;
case TAG_INTEROP_OFFSET:
  processDirectory(metadata.getDirectory(ExifInteropDirectory.class),processedDirectoryOffsets,subdirOffset,tiffHeaderOffset,metadata);
continue;
case TAG_GPS_INFO_OFFSET:
processDirectory(metadata.getDirectory(GpsDirectory.class),processedDirectoryOffsets,subdirOffset,tiffHeaderOffset,metadata);
continue;
case TAG_MAKER_NOTE:
processMakerNote(tagValueOffset,processedDirectoryOffsets,tiffHeaderOffset,metadata);
continue;
default :
processTag(directory,tagType,tagValueOffset,componentCount,formatCode);
break;
}
}
final int finalTagOffset=calculateTagOffset(dirStartOffset,dirTagCount);
int nextDirectoryOffset=get32Bits(finalTagOffset);
if (nextDirectoryOffset != 0) {
nextDirectoryOffset+=tiffHeaderOffset;
if (nextDirectoryOffset >= _data.length) {
return;
}
 else if (nextDirectoryOffset < dirStartOffset) {
return;
}
processDirectory(directory,processedDirectoryOffsets,nextDirectoryOffset,tiffHeaderOffset,metadata);
}
}