zlibによってデータを圧縮できる関数FCompression::CompressMemory()ですが、COMPRESS_GZIPフラグをECompressionFlagsとして渡した際の処理に不具合と思われる現象が発生します。利用しているUE4のバージョンは4.21です。
説明のために、FCompression::CompressMemory()のリファレンスを先に記載します。
static [CORE_API](API\Runtime\Core\Misc\CORE_API_1) bool CompressMemory
(
ECompressionFlags Flags,
void * CompressedBuffer,
int32 & CompressedSize,
const void * UncompressedBuffer,
int32 UncompressedSize,
int32 BitWindow
)
FCompression::CompressMemory()を呼び出す際、圧縮前のデータ(CompressedBufferとCompressedSize)が短かったり、圧縮がかかりにくいデータ(ランダムなバイト列など)である場合に、出力バッファーのサイズ(UncompressedSize)を十分に大きくしても失敗します。
原因を調べるためUE4エンジンのソースコードを確認したところ、FCompression::CompressMemory()の内部で呼び出されるappCompressMemoryGZIP()に不具合と思われる点がありました。
static bool appCompressMemoryGZIP(void* CompressedBuffer, int32& CompressedSize, const void* UncompressedBuffer, int32 UncompressedSize)
{
DECLARE_SCOPE_CYCLE_COUNTER( TEXT( "Compress Memory GZIP" ), STAT_appCompressMemoryGZIP, STATGROUP_Compression );
/* 途中省略 */
// Setup output buffer
const unsigned long GzipHeaderLength = 12;
// This is how much memory we may need, however the consumer is allocating memory for us without knowing the required length.
//unsigned long CompressedMaxSize = deflateBound(&gzipstream, gzipstream.avail_in) + GzipHeaderLength;
gzipstream.next_out = (uint8*)CompressedBuffer;
gzipstream.avail_out = UncompressedSize; // **CompressedSizeを代入すべきでは?**
int status = 0;
bool bOperationSucceeded = false;
while ((status = deflate(&gzipstream, Z_FINISH)) == Z_OK);
上記のコード中のgzipstream.avail_outへ値を設定している箇所で、出力バッファーサイズを設定すべきところに入力バッファーサイズを誤って設定しているように見受けられます。
これは既知の問題でしょうか?また、将来のエンジンのアップデートで修正されますでしょうか?