in csharp/src/ZStdDecompress.cs [683:821]
static size_t DecodeLiteralsBlock(ZSTD_DCtx dctx, void* src, size_t srcSize) /* note : srcSize < BLOCKSIZE */
{
if (srcSize < MIN_CBLOCK_SIZE) return ERROR(Error.corruption_detected);
{
BYTE* istart = (BYTE*)src;
symbolEncodingType_e litEncType = (symbolEncodingType_e)(istart[0] & 3);
switch (litEncType)
{
case symbolEncodingType_e.set_repeat:
case symbolEncodingType_e.set_compressed:
/* fall-through */
if (litEncType == symbolEncodingType_e.set_repeat)
if (dctx.litEntropy == 0) return ERROR(Error.dictionary_corrupted);
if (srcSize < 5) return ERROR(Error.corruption_detected); /* srcSize >= MIN_CBLOCK_SIZE == 3; here we need up to 5 for case 3 */
{
size_t lhSize, litSize, litCSize;
bool singleStream = false;
U32 lhlCode = ((U32)istart[0] >> 2) & 3;
U32 lhc = MEM_readLE32(istart);
switch (lhlCode)
{
case 0:
case 1:
default: /* note : default is impossible, since lhlCode into [0..3] */
/* 2 - 2 - 10 - 10 */
singleStream = lhlCode == 0;
lhSize = 3;
litSize = (lhc >> 4) & 0x3FF;
litCSize = (lhc >> 14) & 0x3FF;
break;
case 2:
/* 2 - 2 - 14 - 14 */
lhSize = 4;
litSize = (lhc >> 4) & 0x3FFF;
litCSize = lhc >> 18;
break;
case 3:
/* 2 - 2 - 18 - 18 */
lhSize = 5;
litSize = (lhc >> 4) & 0x3FFFF;
litCSize = (lhc >> 22) + ((U32)istart[4] << 10);
break;
}
if (litSize > ZSTD_BLOCKSIZE_MAX) return ERROR(Error.corruption_detected);
if (litCSize + lhSize > srcSize) return ERROR(Error.corruption_detected);
if (IsError((litEncType == symbolEncodingType_e.set_repeat) ?
(singleStream ?
HUF_decompress1X_usingDTable_bmi2(dctx.litBuffer, litSize, istart + lhSize, litCSize, dctx.HUFptr/*, dctx.bmi2*/) :
HUF_decompress4X_usingDTable_bmi2(dctx.litBuffer, litSize, istart + lhSize, litCSize, dctx.HUFptr/*, dctx.bmi2*/)) :
(singleStream ?
HUF_decompress1X2_DCtx_wksp_bmi2(dctx.entropy.hufTable, dctx.litBuffer, litSize, istart + lhSize, litCSize,
dctx.entropy.workspace, sizeof(U32) * HUF_DECOMPRESS_WORKSPACE_SIZE_U32/*, dctx.bmi2*/) :
HUF_decompress4X_hufOnly_wksp_bmi2(dctx.entropy.hufTable, dctx.litBuffer, litSize, istart + lhSize, litCSize,
dctx.entropy.workspace, sizeof(U32) * HUF_DECOMPRESS_WORKSPACE_SIZE_U32/*, dctx.bmi2*/))))
return ERROR(Error.corruption_detected);
dctx.litPtr = dctx.litBuffer;
dctx.litSize = litSize;
dctx.litEntropy = 1;
if (litEncType == symbolEncodingType_e.set_compressed) dctx.HUFptr = dctx.entropy.hufTable;
memset(dctx.litBuffer + dctx.litSize, 0, WILDCOPY_OVERLENGTH);
return litCSize + lhSize;
}
case symbolEncodingType_e.set_basic:
{
size_t litSize, lhSize;
U32 lhlCode = ((U32)istart[0] >> 2) & 3;
switch (lhlCode)
{
case 0:
case 2:
default: /* note : default is impossible, since lhlCode into [0..3] */
lhSize = 1;
litSize = (U32)istart[0] >> 3;
break;
case 1:
lhSize = 2;
litSize = MEM_readLE16(istart) >> 4;
break;
case 3:
lhSize = 3;
litSize = MEM_readLE24(istart) >> 4;
break;
}
if (lhSize + litSize + WILDCOPY_OVERLENGTH > srcSize)
{ /* risk reading beyond src buffer with wildcopy */
if (litSize + lhSize > srcSize) return ERROR(Error.corruption_detected);
memcpy(dctx.litBuffer, istart + lhSize, litSize);
dctx.litPtr = dctx.litBuffer;
dctx.litSize = litSize;
memset(dctx.litBuffer + dctx.litSize, 0, WILDCOPY_OVERLENGTH);
return lhSize + litSize;
}
/* direct reference into compressed stream */
dctx.litPtr = istart + lhSize;
dctx.litSize = litSize;
return lhSize + litSize;
}
case symbolEncodingType_e.set_rle:
{
U32 lhlCode = ((U32)istart[0] >> 2) & 3;
size_t litSize, lhSize;
switch (lhlCode)
{
case 0:
case 2:
default: /* note : default is impossible, since lhlCode into [0..3] */
lhSize = 1;
litSize = (U32)istart[0] >> 3;
break;
case 1:
lhSize = 2;
litSize = MEM_readLE16(istart) >> 4;
break;
case 3:
lhSize = 3;
litSize = MEM_readLE24(istart) >> 4;
if (srcSize < 4) return ERROR(Error.corruption_detected); /* srcSize >= MIN_CBLOCK_SIZE == 3; here we need lhSize+1 = 4 */
break;
}
if (litSize > ZSTD_BLOCKSIZE_MAX) return ERROR(Error.corruption_detected);
memset(dctx.litBuffer, istart[lhSize], litSize + WILDCOPY_OVERLENGTH);
dctx.litPtr = dctx.litBuffer;
dctx.litSize = litSize;
return lhSize + 1;
}
default:
return ERROR(Error.corruption_detected); /* impossible */
}
}
}