Program: 15743
Project: 15743
Buggy source:
/** 
 * Compress a number of bytes.
 * @param in the input data
 * @param out the output area
 * @param outPos the offset at the output array
 * @return the end position
 */
public int compress(ByteBuffer in,byte[] out,int outPos){
  int inPos=in.position();
  int inLen=in.capacity() - inPos;
  if (cachedHashTable == null) {
    cachedHashTable=new int[HASH_SIZE];
  }
  int[] hashTab=cachedHashTable;
  int literals=0;
  outPos++;
  int future=first(in,0);
  while (inPos < inLen - 4) {
    byte p2=in.get(inPos + 2);
    future=(future << 8) + (p2 & 255);
    int off=hash(future);
    int ref=hashTab[off];
    hashTab[off]=inPos;
    if (ref < inPos && ref > 0 && (off=inPos - ref - 1) < MAX_OFF && in.get(ref + 2) == p2 && in.get(ref + 1) == (byte)(future >> 8) && in.get(ref) == (byte)(future >> 16)) {
      int maxLen=inLen - inPos - 2;
      if (maxLen > MAX_REF) {
        maxLen=MAX_REF;
      }
      if (literals == 0) {
        outPos--;
      }
 else {
        out[outPos - literals - 1]=(byte)(literals - 1);
        literals=0;
      }
      int len=3;
      while (len < maxLen && in.get(ref + len) == in.get(inPos + len)) {
        len++;
      }
      len-=2;
      if (len < 7) {
        out[outPos++]=(byte)((off >> 8) + (len << 5));
      }
 else {
        out[outPos++]=(byte)((off >> 8) + (7 << 5));
        out[outPos++]=(byte)(len - 7);
      }
      out[outPos++]=(byte)off;
      outPos++;
      inPos+=len;
      future=first(in,inPos);
      future=next(future,in,inPos);
      hashTab[hash(future)]=inPos++;
      future=next(future,in,inPos);
      hashTab[hash(future)]=inPos++;
    }
 else {
      out[outPos++]=in.get(inPos++);
      literals++;
      if (literals == MAX_LITERAL) {
        out[outPos - literals - 1]=(byte)(literals - 1);
        literals=0;
        outPos++;
      }
    }
  }
  while (inPos < inLen) {
    out[outPos++]=in.get(inPos++);
    literals++;
    if (literals == MAX_LITERAL) {
      out[outPos - literals - 1]=(byte)(literals - 1);
      literals=0;
      outPos++;
    }
  }
  out[outPos - literals - 1]=(byte)(literals - 1);
  if (literals == 0) {
    outPos--;
  }
  return outPos;
}

Fixed version (ground truth):
/** 
 * Compress a number of bytes.
 * @param in the input data
 * @param inPos the offset at the input buffer
 * @param out the output area
 * @param outPos the offset at the output array
 * @return the end position
 */
public int compress(ByteBuffer in,int inPos,byte[] out,int outPos){
  int inLen=in.capacity() - inPos;
  if (cachedHashTable == null) {
    cachedHashTable=new int[HASH_SIZE];
  }
  int[] hashTab=cachedHashTable;
  int literals=0;
  outPos++;
  int future=first(in,0);
  while (inPos < inLen - 4) {
    byte p2=in.get(inPos + 2);
    future=(future << 8) + (p2 & 255);
    int off=hash(future);
    int ref=hashTab[off];
    hashTab[off]=inPos;
    if (ref < inPos && ref > 0 && (off=inPos - ref - 1) < MAX_OFF && in.get(ref + 2) == p2 && in.get(ref + 1) == (byte)(future >> 8) && in.get(ref) == (byte)(future >> 16)) {
      int maxLen=inLen - inPos - 2;
      if (maxLen > MAX_REF) {
        maxLen=MAX_REF;
      }
      if (literals == 0) {
        outPos--;
      }
 else {
        out[outPos - literals - 1]=(byte)(literals - 1);
        literals=0;
      }
      int len=3;
      while (len < maxLen && in.get(ref + len) == in.get(inPos + len)) {
        len++;
      }
      len-=2;
      if (len < 7) {
        out[outPos++]=(byte)((off >> 8) + (len << 5));
      }
 else {
        out[outPos++]=(byte)((off >> 8) + (7 << 5));
        out[outPos++]=(byte)(len - 7);
      }
      out[outPos++]=(byte)off;
      outPos++;
      inPos+=len;
      future=first(in,inPos);
      future=next(future,in,inPos);
      hashTab[hash(future)]=inPos++;
      future=next(future,in,inPos);
      hashTab[hash(future)]=inPos++;
    }
 else {
      out[outPos++]=in.get(inPos++);
      literals++;
      if (literals == MAX_LITERAL) {
        out[outPos - literals - 1]=(byte)(literals - 1);
        literals=0;
        outPos++;
      }
    }
  }
  while (inPos < inLen) {
    out[outPos++]=in.get(inPos++);
    literals++;
    if (literals == MAX_LITERAL) {
      out[outPos - literals - 1]=(byte)(literals - 1);
      literals=0;
      outPos++;
    }
  }
  out[outPos - literals - 1]=(byte)(literals - 1);
  if (literals == 0) {
    outPos--;
  }
  return outPos;
}