diff --git a/lib/decompress/zstd_decompress.c b/lib/decompress/zstd_decompress.c index 325f0b54dfc..4a97abe40e8 100644 --- a/lib/decompress/zstd_decompress.c +++ b/lib/decompress/zstd_decompress.c @@ -465,6 +465,9 @@ size_t ZSTD_getFrameHeader_advanced(ZSTD_FrameHeader* zfhPtr, const void* src, s assert(src != NULL); ZSTD_memcpy(hbuf, src, toCopy); if ( MEM_readLE32(hbuf) != ZSTD_MAGICNUMBER ) { +#if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT>=1) + if (ZSTD_isLegacy(hbuf, 4)) return minInputSize; /* legacy frames are supported too */ +#endif /* not a zstd frame : let's check if it's a skippable frame */ MEM_writeLE32(hbuf, ZSTD_MAGIC_SKIPPABLE_START); ZSTD_memcpy(hbuf, src, toCopy); @@ -2140,7 +2143,7 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB } if (ZSTD_isError(hSize)) { #if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT>=1) - U32 const legacyVersion = ZSTD_isLegacy(istart, iend-istart); + U32 const legacyVersion = ZSTD_isLegacy(zds->headerBuffer, zds->lhSize); if (legacyVersion) { ZSTD_DDict const* const ddict = ZSTD_getDDict(zds); const void* const dict = ddict ? ZSTD_DDict_dictContent(ddict) : NULL; @@ -2152,7 +2155,13 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB zds->previousLegacyVersion, legacyVersion, dict, dictSize), ""); zds->legacyVersion = zds->previousLegacyVersion = legacyVersion; - { size_t const hint = ZSTD_decompressLegacyStream(zds->legacyContext, legacyVersion, output, input); + { /* the frame header may have been buffered by previous calls : replay it first */ + ZSTD_inBuffer header; + size_t hint; + header.src = zds->headerBuffer; header.size = zds->lhSize; header.pos = 0; + FORWARD_IF_ERROR(ZSTD_decompressLegacyStream(zds->legacyContext, legacyVersion, output, &header), ""); + input->pos = (size_t)(ip - (const char*)(input->src)); + hint = ZSTD_decompressLegacyStream(zds->legacyContext, legacyVersion, output, input); if (hint==0) zds->streamStage = zdss_init; /* or stay in stage zdss_loadHeader */ return hint; } } diff --git a/tests/legacy.c b/tests/legacy.c index 18a590f1d51..81bfd423f3e 100644 --- a/tests/legacy.c +++ b/tests/legacy.c @@ -156,8 +156,10 @@ static int testSimpleAPI(const char* compressed, size_t compressedSize, } +/* @maxChunk : nb of bytes given to each ZSTD_decompressStream() call */ static int testStreamingAPI(const char* compressed, size_t compressedSize, - const char* expected, size_t expectedSize) + const char* expected, size_t expectedSize, + size_t maxChunk) { int error_code = 0; size_t const outBuffSize = ZSTD_DStreamOutSize(); @@ -168,7 +170,6 @@ static int testStreamingAPI(const char* compressed, size_t compressedSize, int needsInit = 1; input.src = compressed; - input.size = compressedSize; if (outBuff == NULL) { DISPLAY("ERROR: Could not allocate memory\n"); @@ -182,13 +183,16 @@ static int testStreamingAPI(const char* compressed, size_t compressedSize, while (1) { ZSTD_outBuffer output = {outBuff, outBuffSize, 0}; + input.size = (compressedSize - input.pos > maxChunk) ? input.pos + maxChunk : compressedSize; if (needsInit) { size_t const ret = ZSTD_initDStream(stream); if (ZSTD_isError(ret)) { DISPLAY("ERROR: ZSTD_initDStream: %s\n", ZSTD_getErrorName(ret)); error_code = 1; break; - } } + } + needsInit = 0; + } { size_t const ret = ZSTD_decompressStream(stream, &output, &input); if (ZSTD_isError(ret)) { @@ -212,7 +216,7 @@ static int testStreamingAPI(const char* compressed, size_t compressedSize, break; } outputPos += output.pos; - if (input.pos == input.size && output.pos < output.size) { + if (input.pos == compressedSize && output.pos < output.size) { break; } } @@ -297,7 +301,10 @@ int main(void) /* all blocks being identical, the first @nbStreamFrames ones * are what the streaming subset must decode to */ if (testStreamingAPI(streamable, streamableSize, - expected, blockSize * nbStreamFrames)) break; + expected, blockSize * nbStreamFrames, streamableSize)) break; + /* one byte at a time : frame headers arrive split across calls */ + if (testStreamingAPI(streamable, streamableSize, + expected, blockSize * nbStreamFrames, 1)) break; result = 0; } while (0);