Fix bzip2 compression of files > 4 GiB

Bzip2's 'avail_in' parameter is declared as an unsigned int, so
assigning a size_t length to it led to silent truncation.

Fixes #2111.
This commit is contained in:
Eelco Dolstra 2018-05-02 12:54:30 +02:00
parent 3560654e6a
commit 4a2c948943
No known key found for this signature in database
GPG key ID: 8170B4726D7198DE

View file

@ -368,8 +368,21 @@ struct BzipSink : CompressionSink
} }
void write(const unsigned char * data, size_t len) override void write(const unsigned char * data, size_t len) override
{
/* Bzip2's 'avail_in' parameter is an unsigned int, so we need
to split the input into chunks of at most 4 GiB. */
while (len) {
auto n = std::min((size_t) std::numeric_limits<decltype(strm.avail_in)>::max(), len);
writeInternal(data, n);
data += n;
len -= n;
}
}
void writeInternal(const unsigned char * data, size_t len)
{ {
assert(!finished); assert(!finished);
assert(len <= std::numeric_limits<decltype(strm.avail_in)>::max());
strm.next_in = (char *) data; strm.next_in = (char *) data;
strm.avail_in = len; strm.avail_in = len;
@ -475,8 +488,6 @@ struct BrotliSink : CompressionSink
void write(const unsigned char * data, size_t len) override void write(const unsigned char * data, size_t len) override
{ {
assert(!finished);
// Don't feed brotli too much at once // Don't feed brotli too much at once
const size_t CHUNK_SIZE = sizeof(outbuf) << 2; const size_t CHUNK_SIZE = sizeof(outbuf) << 2;
while (len) { while (len) {
@ -486,7 +497,7 @@ struct BrotliSink : CompressionSink
len -= n; len -= n;
} }
} }
private:
void writeInternal(const unsigned char * data, size_t len) void writeInternal(const unsigned char * data, size_t len)
{ {
assert(!finished); assert(!finished);