File: src/main/java/org/apache/commons/compress/utils/BitInputStream.java
Issue: Overflow in BitInputStream
in Class BitInputStream.java(\src\main\java\org\apache\commons\compress\utils),
funcion:
 public long readBits(final int count) throws IOException {
        if (count < 0 || count > MAXIMUM_CACHE_SIZE) 
{
            throw new IllegalArgumentException("count must not be negative or greater than " + MAXIMUM_CACHE_SIZE);
        }
        while (bitsCachedSize < count) {
            final long nextByte = in.read();
            if (nextByte < 0) 
{
                return nextByte;
            }
            if (byteOrder == ByteOrder.LITTLE_ENDIAN) 
{
                bitsCached |= (nextByte << bitsCachedSize);
            }
 else 
{
                bitsCached <<= 8;
                bitsCached |= nextByte;
            }
            bitsCachedSize += 8;
        }
        final long bitsOut;
        if (byteOrder == ByteOrder.LITTLE_ENDIAN) 
{
            bitsOut = (bitsCached & MASKS[count]);
            bitsCached >>>= count;
        }
 else 
{
            bitsOut = (bitsCached >> (bitsCachedSize - count)) & MASKS[count];
        }
        bitsCachedSize -= count;
        return bitsOut;
    }
I think here "bitsCached |= (nextByte << bitsCachedSize);" will overflow in some cases. for example, below is a test case:
public static void test() {
        ByteArrayInputStream in = new ByteArrayInputStream(new byte[]
{87, 45, 66, 15,
                                                                      90, 29, 88, 61, 33, 74}
);
        BitInputStream bin = new BitInputStream(in, ByteOrder.LITTLE_ENDIAN);
        try 
{
            long ret = bin.readBits(5);
            ret = bin.readBits(63);
            ret = bin.readBits(12);
        }
 catch (Exception e) 
{
            e.printStackTrace();
        }
}
overflow occur in "bin.readBits(63);" , so ,result in wrong result from  "bin.readBits(12);"

Buggy code:
public long readBits(final int count) throws IOException {
    if (count < 0 || count > MAXIMUM_CACHE_SIZE) {
        throw new IllegalArgumentException("count must not be negative or greater than " + MAXIMUM_CACHE_SIZE);
    }
    while (bitsCachedSize < count) {
        final long nextByte = in.read();
        if (nextByte < 0) {
            return nextByte;
        }
        if (byteOrder == ByteOrder.LITTLE_ENDIAN) {
            bitsCached |= (nextByte << bitsCachedSize);
        } else {
            bitsCached <<= 8;
            bitsCached |= nextByte;
        }
        bitsCachedSize += 8;
    }
        // bitsCachedSize >= 57 and left-shifting it 8 bits would cause an overflow
    
    final long bitsOut;
        if (byteOrder == ByteOrder.LITTLE_ENDIAN) {
            bitsOut = (bitsCached & MASKS[count]);
            bitsCached >>>= count;
        } else {
            bitsOut = (bitsCached >> (bitsCachedSize - count)) & MASKS[count];
        }
        bitsCachedSize -= count;
    return bitsOut;
}

Fixed code:
public long readBits(final int count) throws IOException {
    if (count < 0 || count > MAXIMUM_CACHE_SIZE) {
        throw new IllegalArgumentException("count must not be negative or greater than " + MAXIMUM_CACHE_SIZE);
    }
    while (bitsCachedSize < count && bitsCachedSize < 57) {
        final long nextByte = in.read();
        if (nextByte < 0) {
            return nextByte;
        }
        if (byteOrder == ByteOrder.LITTLE_ENDIAN) {
            bitsCached |= (nextByte << bitsCachedSize);
        } else {
            bitsCached <<= 8;
            bitsCached |= nextByte;
        }
        bitsCachedSize += 8;
    }
    int overflowBits = 0;
    long overflow = 0l;
    if (bitsCachedSize < count) {
        // bitsCachedSize >= 57 and left-shifting it 8 bits would cause an overflow
        int bitsToAddCount = count - bitsCachedSize;
        overflowBits = 8 - bitsToAddCount;
        final long nextByte = in.read();
        if (nextByte < 0) {
            return nextByte;
        }
        if (byteOrder == ByteOrder.LITTLE_ENDIAN) {
            long bitsToAdd = nextByte & MASKS[bitsToAddCount];
            bitsCached |= (bitsToAdd << bitsCachedSize);
            overflow = (nextByte >>> bitsToAddCount) & MASKS[overflowBits];
        } else {
            bitsCached <<= bitsToAddCount;
            long bitsToAdd = (nextByte >>> (overflowBits)) & MASKS[bitsToAddCount];
            bitsCached |= bitsToAdd;
            overflow = nextByte & MASKS[overflowBits];
        }
        bitsCachedSize = count;
    }
    
    final long bitsOut;
    if (overflowBits == 0) {
        if (byteOrder == ByteOrder.LITTLE_ENDIAN) {
            bitsOut = (bitsCached & MASKS[count]);
            bitsCached >>>= count;
        } else {
            bitsOut = (bitsCached >> (bitsCachedSize - count)) & MASKS[count];
        }
        bitsCachedSize -= count;
    } else {
        bitsOut = bitsCached & MASKS[count];
        bitsCached = overflow;
        bitsCachedSize = overflowBits;
    }
    return bitsOut;
}