Read the compressed data as a stream

This avoids allocating the complete buffer at first based solely
on the value read from the frame header.  This then does a sanity
check at the end of reading to make sure that the two values match.
At present, it just prints a debugging message if the values do not
match.

Fixes #466
This commit is contained in:
Scott Wheeler 2015-01-04 19:58:18 +01:00
parent 31982660c8
commit caa53e8de5

View File

@ -254,12 +254,44 @@ ByteVector Frame::fieldData(const ByteVector &frameData) const
if(d->header->compression() &&
!d->header->encryption())
{
ByteVector data(frameDataLength);
uLongf uLongTmp = frameDataLength;
::uncompress((Bytef *) data.data(),
(uLongf *) &uLongTmp,
(Bytef *) frameData.data() + frameDataOffset,
size());
z_stream stream;
memset(&stream, 0, sizeof(z_stream));
if(inflateInit(&stream) != Z_OK)
return ByteVector();
stream.avail_in = (uLongf) frameDataLength;
stream.next_in = (Bytef *) frameData.data() + frameDataOffset;
static const uint chunkSize = 1024;
ByteVector data;
ByteVector chunk(chunkSize);
do {
stream.avail_out = (uLongf) chunk.size();
stream.next_out = (Bytef *) chunk.data();
int result = inflate(&stream, Z_NO_FLUSH);
if(result == Z_STREAM_ERROR)
return ByteVector();
else if(result == Z_NEED_DICT ||
result == Z_DATA_ERROR ||
result == Z_MEM_ERROR)
{
inflateEnd(&stream);
return ByteVector();
}
data.append(stream.avail_out == 0 ? chunk : chunk.mid(0, chunk.size() - stream.avail_out));
} while(stream.avail_out == 0);
inflateEnd(&stream);
if(frameDataLength != data.size())
debug("frameDataLength does not match the data length returned by zlib");
return data;
}
else