File: src/main/java/org/apache/commons/compress/archivers/zip/ZipArchiveInputStream.java
Issue: ZipArchiveInputStream doesn't report the end of a truncated archive
If a Zip archive is truncated, (e.g. because it is the first volume in a multi-volume archive) the ZipArchiveInputStream.read() method will not detect that fact. All calls to read() will return 0 bytes read. They will not return -1 (end of stream), nor will they throw any exception (which would seem like a good idea to me because the archive is truncated).
I have tracked this problem to ZipArchiveInputStream.java, line 239. It contains a check
if (read == 0 && inf.finished()) {
    return -1;
}
For truncated archives the read is always zero but the inf is never finished(). I suggest adding two lines below:
if (read == 0 && inf.finished()) {
    return -1;
} else if (read == 0 && lengthOfLastRead == -1) {
	throw new IOException("Truncated ZIP file");
}
This solves the problem in my tests.

Buggy code:
public int read(byte[] buffer, int start, int length) throws IOException {
    if (closed) {
        throw new IOException("The stream is closed");
    }
    if (inf.finished() || current == null) {
        return -1;
    }

    // avoid int overflow, check null buffer
    if (start <= buffer.length && length >= 0 && start >= 0
        && buffer.length - start >= length) {
        if (current.getMethod() == ZipArchiveOutputStream.STORED) {
            int csize = (int) current.getSize();
            if (readBytesOfEntry >= csize) {
                return -1;
            }
            if (offsetInBuffer >= lengthOfLastRead) {
                offsetInBuffer = 0;
                if ((lengthOfLastRead = in.read(buf)) == -1) {
                    return -1;
                }
                count(lengthOfLastRead);
                bytesReadFromStream += lengthOfLastRead;
            }
            int toRead = length > lengthOfLastRead
                ? lengthOfLastRead - offsetInBuffer
                : length;
            if ((csize - readBytesOfEntry) < toRead) {
                toRead = csize - readBytesOfEntry;
            }
            System.arraycopy(buf, offsetInBuffer, buffer, start, toRead);
            offsetInBuffer += toRead;
            readBytesOfEntry += toRead;
            crc.update(buffer, start, toRead);
            return toRead;
        }
        if (inf.needsInput()) {
            fill();
            if (lengthOfLastRead > 0) {
                bytesReadFromStream += lengthOfLastRead;
            }
        }
        int read = 0;
        try {
            read = inf.inflate(buffer, start, length);
        } catch (DataFormatException e) {
            throw new ZipException(e.getMessage());
        }
        if (read == 0 && inf.finished()) {
            return -1;
        }
        crc.update(buffer, start, read);
        return read;
    }
    throw new ArrayIndexOutOfBoundsException();
}

Fixed code:
public int read(byte[] buffer, int start, int length) throws IOException {
    if (closed) {
        throw new IOException("The stream is closed");
    }
    if (inf.finished() || current == null) {
        return -1;
    }

    // avoid int overflow, check null buffer
    if (start <= buffer.length && length >= 0 && start >= 0
        && buffer.length - start >= length) {
        if (current.getMethod() == ZipArchiveOutputStream.STORED) {
            int csize = (int) current.getSize();
            if (readBytesOfEntry >= csize) {
                return -1;
            }
            if (offsetInBuffer >= lengthOfLastRead) {
                offsetInBuffer = 0;
                if ((lengthOfLastRead = in.read(buf)) == -1) {
                    return -1;
                }
                count(lengthOfLastRead);
                bytesReadFromStream += lengthOfLastRead;
            }
            int toRead = length > lengthOfLastRead
                ? lengthOfLastRead - offsetInBuffer
                : length;
            if ((csize - readBytesOfEntry) < toRead) {
                toRead = csize - readBytesOfEntry;
            }
            System.arraycopy(buf, offsetInBuffer, buffer, start, toRead);
            offsetInBuffer += toRead;
            readBytesOfEntry += toRead;
            crc.update(buffer, start, toRead);
            return toRead;
        }
        if (inf.needsInput()) {
            fill();
            if (lengthOfLastRead > 0) {
                bytesReadFromStream += lengthOfLastRead;
            }
        }
        int read = 0;
        try {
            read = inf.inflate(buffer, start, length);
        } catch (DataFormatException e) {
            throw new ZipException(e.getMessage());
        }
        if (read == 0) {
            if (inf.finished()) {
                return -1;
            } else if (lengthOfLastRead == -1) {
                throw new IOException("Truncated ZIP file");
            }
        }
        crc.update(buffer, start, read);
        return read;
    }
    throw new ArrayIndexOutOfBoundsException();
}