File: src/main/java/org/apache/commons/compress/compressors/bzip2/BZip2CompressorInputStream.java
Issue: BZip2CompressorInputStream return value wrong when told to read to a full buffer.
BZip2CompressorInputStream.read(buffer, offset, length) returns -1 when given an offset equal to the length of the buffer.
This indicates, not that the buffer was full, but that the stream was finished.
It seems like a pretty stupid thing to do - but I'm getting this when trying to use Kryo serialization (which is probably a bug on their part, too), so it does occur and has negative affects.
Here's a JUnit test that shows the problem specifically:

	@Test
	public void testApacheCommonsBZipUncompression () throws Exception {
		// Create a big random piece of data
		byte[] rawData = new byte[1048576];
		for (int i=0; i<rawData.length; ++i) {
			rawData[i] = (byte) Math.floor(Math.random()*256);
		}

		// Compress it
		ByteArrayOutputStream baos = new ByteArrayOutputStream();
		BZip2CompressorOutputStream bzipOut = new BZip2CompressorOutputStream(baos);
		bzipOut.write(rawData);
		bzipOut.flush();
		bzipOut.close();
		baos.flush();
		baos.close();

		// Try to read it back in
		ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
		BZip2CompressorInputStream bzipIn = new BZip2CompressorInputStream(bais);
		byte[] buffer = new byte[1024];
		// Works fine
		Assert.assertEquals(1024, bzipIn.read(buffer, 0, 1024));
		// Fails, returns -1 (indicating the stream is complete rather than that the buffer 
		// was full)
		Assert.assertEquals(0, bzipIn.read(buffer, 1024, 0));
		// But if you change the above expected value to -1, the following line still works
		Assert.assertEquals(1024, bzipIn.read(buffer, 0, 1024));
		bzipIn.close();
	}

Buggy code:
public int read(final byte[] dest, final int offs, final int len)
    throws IOException {
    if (offs < 0) {
        throw new IndexOutOfBoundsException("offs(" + offs + ") < 0.");
    }
    if (len < 0) {
        throw new IndexOutOfBoundsException("len(" + len + ") < 0.");
    }
    if (offs + len > dest.length) {
        throw new IndexOutOfBoundsException("offs(" + offs + ") + len("
                                            + len + ") > dest.length(" + dest.length + ").");
    }
    if (this.in == null) {
        throw new IOException("stream closed");
    }

    final int hi = offs + len;
    int destOffs = offs;
    int b;
    while (destOffs < hi && ((b = read0()) >= 0)) {
        dest[destOffs++] = (byte) b;
        count(1);
    }

    int c = (destOffs == offs) ? -1 : (destOffs - offs);
    return c;
}

Fixed code:
public int read(final byte[] dest, final int offs, final int len)
    throws IOException {
    if (offs < 0) {
        throw new IndexOutOfBoundsException("offs(" + offs + ") < 0.");
    }
    if (len < 0) {
        throw new IndexOutOfBoundsException("len(" + len + ") < 0.");
    }
    if (offs + len > dest.length) {
        throw new IndexOutOfBoundsException("offs(" + offs + ") + len("
                                            + len + ") > dest.length(" + dest.length + ").");
    }
    if (this.in == null) {
        throw new IOException("stream closed");
    }
    if (len == 0) {
        return 0;
    }

    final int hi = offs + len;
    int destOffs = offs;
    int b;
    while (destOffs < hi && ((b = read0()) >= 0)) {
        dest[destOffs++] = (byte) b;
        count(1);
    }

    int c = (destOffs == offs) ? -1 : (destOffs - offs);
    return c;
}