in csharp/src/ZStdDecompress.cs [2008:2091]
static size_t DecompressFrame(ZSTD_DCtx dctx,
void* dst, size_t dstCapacity,
void** srcPtr, size_t* srcSizePtr)
{
BYTE* ip = (BYTE*)(*srcPtr);
BYTE* ostart = (BYTE*)dst;
BYTE* oend = ostart + dstCapacity;
BYTE* op = ostart;
size_t remainingSize = *srcSizePtr;
/* check */
if (remainingSize < ZSTD_frameHeaderSize_min + ZSTD_blockHeaderSize)
return ERROR(Error.srcSize_wrong);
/* Frame Header */
{
size_t frameHeaderSize = FrameHeaderSize(ip, ZSTD_frameHeaderSize_prefix);
if (IsError(frameHeaderSize)) return frameHeaderSize;
if (remainingSize < frameHeaderSize + ZSTD_blockHeaderSize)
return ERROR(Error.srcSize_wrong);
{ size_t errcod = DecodeFrameHeader(dctx, ip, frameHeaderSize); if (IsError(errcod)) return errcod; }
ip += frameHeaderSize; remainingSize -= frameHeaderSize;
}
/* Loop on each block */
while (true)
{
size_t decodedSize;
blockProperties_t blockProperties;
size_t cBlockSize = GetcBlockSize(ip, remainingSize, &blockProperties);
if (IsError(cBlockSize)) return cBlockSize;
ip += ZSTD_blockHeaderSize;
remainingSize -= ZSTD_blockHeaderSize;
if (cBlockSize > remainingSize) return ERROR(Error.srcSize_wrong);
switch (blockProperties.blockType)
{
case blockType_e.bt_compressed:
decodedSize = ZSTD_decompressBlock_internal(dctx, op, (size_t)(oend - op), ip, cBlockSize, /* frame */ 1);
break;
case blockType_e.bt_raw:
decodedSize = CopyRawBlock(op, (size_t)(oend - op), ip, cBlockSize);
break;
case blockType_e.bt_rle:
decodedSize = GenerateNxBytes(op, (size_t)(oend - op), *ip, blockProperties.origSize);
break;
case blockType_e.bt_reserved:
default:
return ERROR(Error.corruption_detected);
}
if (IsError(decodedSize)) return decodedSize;
if (dctx.fParams.checksumFlag != 0)
XXH64_update(dctx.xxhState, op, decodedSize);
op += decodedSize;
ip += cBlockSize;
remainingSize -= cBlockSize;
if (blockProperties.lastBlock != 0) break;
}
if (dctx.fParams.frameContentSize != ZSTD_CONTENTSIZE_UNKNOWN)
{
if ((U64)(op - ostart) != dctx.fParams.frameContentSize)
{
return ERROR(Error.corruption_detected);
}
}
if (dctx.fParams.checksumFlag != 0)
{ /* Frame content checksum verification */
U32 checkCalc = (U32)XXH64_digest(dctx.xxhState);
U32 checkRead;
if (remainingSize < 4) return ERROR(Error.checksum_wrong);
checkRead = MEM_readLE32(ip);
if (checkRead != checkCalc) return ERROR(Error.checksum_wrong);
ip += 4;
remainingSize -= 4;
}
/* Allow caller to get size read */
*srcPtr = ip;
*srcSizePtr = remainingSize;
return (size_t)(op - ostart);
}