LZ4_decompress_safe
的文档说明:
/*! LZ4_decompress_safe() : compressedSize : is the precise full size of the compressed block. maxDecompressedSize : is the size of destination buffer, which must be already allocated. return : the number of bytes decompressed into destination buffer (necessarily <= maxDecompressedSize) If destination buffer is not large enough, decoding will stop and output an error code (<0). If the source stream is detected malformed, the function will stop decoding and return a negative result. This function is protected against buffer overflow exploits, including malicious data packets. It never writes outside output buffer, nor reads outside input buffer. */ LZ4LIB_API int LZ4_decompress_safe (const char* source, char* dest, int compressedSize, int maxDecompressedSize);
但没有指定如何区分问题是由于目标缓冲区太小,还是由于输入错误/参数组合错误/。。。
在我不知道目标解压缩大小的情况下,我如何知道是否应该使用更大的缓冲区重试?
这方面存在一个问题,目前还没有公共的API来区分错误。
作为启发式,查看代码显示可能的返回值:
/* end of decoding */ if (endOnInput) return (int) (((char*)op)-dest); /* Nb of output bytes decoded */ else return (int) (((const char*)ip)-source); /* Nb of input bytes read */ /* Overflow error detected */ _output_error: return (int) (-(((const char*)ip)-source))-1;
所以只有两种情况:
- 要么解码成功,你就会得到一个积极的结果(其意义取决于你是处于完全模式还是部分模式)
- 或者解码失败,得到否定结果
在否定结果的情况下,值为-(position_in_input + 1)
。
这表明,通过使用(大得多的)缓冲区重试,并检查故障是否发生在相同的位置,可以很有可能成功地猜测目标缓冲区是否太小:
- 如果第二次解压缩尝试成功,那就太好了
- 如果第二次解压缩尝试在相同位置失败
- 否则,您必须再次尝试使用更大的缓冲区
或者换句话说,只要结果不同,就再试一次,否则就是你的结果。
限制
输入指针不一定每次前进一个字节,它可以在从输入读取length
并且无边界的两个位置前进length
字节。
如果由于输出缓冲区太小而导致解码失败,并且新的输出缓冲区对于length
来说仍然太小,则即使输入不一定格式错误,解码也将在相同位置失败。
如果误报是一个问题,那么可以尝试:
- 通过检查返回位置处的输入流来解码
length
- 只需根据Mark Adler的答案分配
255 * <input size> - 2526
,这对于小输入来说是合理的