Program: 77405
Project: 77405
Buggy source:
/** 
 * Reads up to <code>len</code> bytes of data from this piped input stream into an array of bytes. Less than <code>len</code> bytes will be read if the end of the data stream is reached or if <code>len</code> exceeds the pipe's buffer size. If <code>len </code> is zero, then no bytes are read and 0 is returned; otherwise, the method blocks until at least 1 byte of input is available, end of the stream has been detected, or an exception is thrown.
 * @param b     the buffer into which the data is read.
 * @param off   the start offset in the destination array <code>b</code>
 * @param len   the maximum number of bytes read.
 * @return     the total number of bytes read into the buffer, or<code>-1</code> if there is no more data because the end of the stream has been reached.
 * @exception NullPointerException If <code>b</code> is <code>null</code>.
 * @exception IndexOutOfBoundsException If <code>off</code> is negative,<code>len</code> is negative, or <code>len</code> is greater than <code>b.length - off</code>
 * @exception IOException if the pipe is <a href=#BROKEN> <code>broken</code></a>,{@link #connect(java.io.PipedOutputStream) unconnected}, closed, or if an I/O error occurs.
 */
public synchronized int read(byte b[],int off,int len) throws IOException {
  if (b == null) {
    throw new NullPointerException();
  }
 else   if (off < 0 || len < 0 || len > b.length - off) {
    throw new IndexOutOfBoundsException();
  }
 else   if (len == 0) {
    return 0;
  }
  int c=read();
  if (c < 0) {
    return -1;
  }
  b[off]=(byte)c;
  int rlen=1;
  while ((in >= 0) && (len > 1)) {
    int available;
    if (in > out) {
      available=Math.min((buffer.length - out),(in - out));
    }
 else {
      available=buffer.length - out;
    }
    if (available > (len - 1)) {
      available=len - 1;
    }
    System.arraycopy(buffer,out,b,off + rlen,available);
    out+=available;
    rlen+=available;
    len-=available;
    if (out >= buffer.length) {
      out=0;
    }
    if (in == out) {
      in=-1;
    }
  }
  return rlen;
}

Fixed version (ground truth):
/** 
 * Reads up to <code>len</code> bytes of data from this piped input stream into an array of bytes. Less than <code>len</code> bytes will be read if the end of the data stream is reached or if <code>len</code> exceeds the pipe's buffer size. If <code>len </code> is zero, then no bytes are read and 0 is returned; otherwise, the method blocks until at least 1 byte of input is available, end of the stream has been detected, or an exception is thrown.
 * @param b     the buffer into which the data is read.
 * @param off   the start offset in the destination array <code>b</code>
 * @param len   the maximum number of bytes read.
 * @return     the total number of bytes read into the buffer, or<code>-1</code> if there is no more data because the end of the stream has been reached.
 * @exception NullPointerException If <code>b</code> is <code>null</code>.
 * @exception IndexOutOfBoundsException If <code>off</code> is negative,<code>len</code> is negative, or <code>len</code> is greater than <code>b.length - off</code>
 * @exception IOException if the pipe is <a href="#BROKEN"> <code>broken</code></a>,{@link #connect(java.io.PipedOutputStream) unconnected}, closed, or if an I/O error occurs.
 */
public synchronized int read(byte b[],int off,int len) throws IOException {
  if (b == null) {
    throw new NullPointerException();
  }
 else   if (off < 0 || len < 0 || len > b.length - off) {
    throw new IndexOutOfBoundsException();
  }
 else   if (len == 0) {
    return 0;
  }
  int c=read();
  if (c < 0) {
    return -1;
  }
  b[off]=(byte)c;
  int rlen=1;
  while ((in >= 0) && (len > 1)) {
    int available;
    if (in > out) {
      available=Math.min((buffer.length - out),(in - out));
    }
 else {
      available=buffer.length - out;
    }
    if (available > (len - 1)) {
      available=len - 1;
    }
    System.arraycopy(buffer,out,b,off + rlen,available);
    out+=available;
    rlen+=available;
    len-=available;
    if (out >= buffer.length) {
      out=0;
    }
    if (in == out) {
      in=-1;
    }
  }
  return rlen;
}