in doom_py/src/vizdoom/lzma/C/7zArcIn.c [1098:1467]
static SRes SzReadHeader2(
CSzArEx *p, /* allocMain */
CSzData *sd,
ILookInStream *inStream,
CBuf *tempBufs, UInt32 *numTempBufs,
ISzAlloc *allocMain,
ISzAlloc *allocTemp
)
{
UInt64 type;
UInt32 numFiles = 0;
UInt32 numEmptyStreams = 0;
CSubStreamInfo ssi;
const Byte *emptyStreams = NULL;
const Byte *emptyFiles = NULL;
SzData_Clear(&ssi.sdSizes);
SzData_Clear(&ssi.sdCRCs);
SzData_Clear(&ssi.sdNumSubStreams);
ssi.NumSubDigests = 0;
ssi.NumTotalSubStreams = 0;
RINOK(ReadID(sd, &type));
if (type == k7zIdArchiveProperties)
{
for (;;)
{
UInt64 type;
RINOK(ReadID(sd, &type));
if (type == k7zIdEnd)
break;
RINOK(SkipData(sd));
}
RINOK(ReadID(sd, &type));
}
if (type == k7zIdAdditionalStreamsInfo)
{
CSzAr tempAr;
SRes res;
SzAr_Init(&tempAr);
res = SzReadAndDecodePackedStreams(inStream, sd, tempBufs, NUM_ADDITIONAL_STREAMS_MAX,
p->startPosAfterHeader, &tempAr, allocTemp);
*numTempBufs = tempAr.NumFolders;
SzAr_Free(&tempAr, allocTemp);
if (res != SZ_OK)
return res;
RINOK(ReadID(sd, &type));
}
if (type == k7zIdMainStreamsInfo)
{
RINOK(SzReadStreamsInfo(&p->db, sd, (UInt32)1 << 30, tempBufs, *numTempBufs,
&p->dataPos, &ssi, allocMain));
p->dataPos += p->startPosAfterHeader;
RINOK(ReadID(sd, &type));
}
if (type == k7zIdEnd)
{
return SZ_OK;
}
if (type != k7zIdFilesInfo)
return SZ_ERROR_ARCHIVE;
RINOK(SzReadNumber32(sd, &numFiles));
p->NumFiles = numFiles;
for (;;)
{
UInt64 type;
UInt64 size;
RINOK(ReadID(sd, &type));
if (type == k7zIdEnd)
break;
RINOK(ReadNumber(sd, &size));
if (size > sd->Size)
return SZ_ERROR_ARCHIVE;
if (type >= ((UInt32)1 << 8))
{
SKIP_DATA(sd, size);
}
else switch ((unsigned)type)
{
case k7zIdName:
{
size_t namesSize;
const Byte *namesData;
Byte external;
SZ_READ_BYTE(external);
if (external == 0)
{
namesSize = (size_t)size - 1;
namesData = sd->Data;
}
else
{
UInt32 index;
RINOK(SzReadNumber32(sd, &index));
if (index >= *numTempBufs)
return SZ_ERROR_ARCHIVE;
namesData = (tempBufs)[index].data;
namesSize = (tempBufs)[index].size;
}
if ((namesSize & 1) != 0)
return SZ_ERROR_ARCHIVE;
MY_ALLOC(size_t, p->FileNameOffsets, numFiles + 1, allocMain);
MY_ALLOC_ZE_AND_CPY(p->FileNames, namesSize, namesData, allocMain);
RINOK(SzReadFileNames(p->FileNames, namesSize, numFiles, p->FileNameOffsets))
if (external == 0)
{
SKIP_DATA(sd, namesSize);
}
break;
}
case k7zIdEmptyStream:
{
RINOK(RememberBitVector(sd, numFiles, &emptyStreams));
numEmptyStreams = CountDefinedBits(emptyStreams, numFiles);
emptyFiles = NULL;
break;
}
case k7zIdEmptyFile:
{
RINOK(RememberBitVector(sd, numEmptyStreams, &emptyFiles));
break;
}
case k7zIdWinAttrib:
{
Byte external;
CSzData sdSwitch;
CSzData *sdPtr;
SzBitUi32s_Free(&p->Attribs, allocMain);
RINOK(ReadBitVector(sd, numFiles, &p->Attribs.Defs, allocMain));
SZ_READ_BYTE(external);
if (external == 0)
sdPtr = sd;
else
{
UInt32 index;
RINOK(SzReadNumber32(sd, &index));
if (index >= *numTempBufs)
return SZ_ERROR_ARCHIVE;
sdSwitch.Data = (tempBufs)[index].data;
sdSwitch.Size = (tempBufs)[index].size;
sdPtr = &sdSwitch;
}
RINOK(ReadUi32s(sdPtr, numFiles, &p->Attribs, allocMain));
break;
}
/*
case k7zParent:
{
SzBitUi32s_Free(&p->Parents, allocMain);
RINOK(ReadBitVector(sd, numFiles, &p->Parents.Defs, allocMain));
RINOK(SzReadSwitch(sd));
RINOK(ReadUi32s(sd, numFiles, &p->Parents, allocMain));
break;
}
*/
case k7zIdMTime: RINOK(ReadTime(&p->MTime, numFiles, sd, tempBufs, *numTempBufs, allocMain)); break;
case k7zIdCTime: RINOK(ReadTime(&p->CTime, numFiles, sd, tempBufs, *numTempBufs, allocMain)); break;
default:
{
SKIP_DATA(sd, size);
}
}
}
if (numFiles - numEmptyStreams != ssi.NumTotalSubStreams)
return SZ_ERROR_ARCHIVE;
for (;;)
{
UInt64 type;
RINOK(ReadID(sd, &type));
if (type == k7zIdEnd)
break;
RINOK(SkipData(sd));
}
{
UInt32 i;
UInt32 emptyFileIndex = 0;
UInt32 folderIndex = 0;
UInt32 remSubStreams = 0;
UInt32 numSubStreams = 0;
UInt64 unpackPos = 0;
const Byte *digestsDefs = NULL;
const Byte *digestsVals = NULL;
UInt32 digestsValsIndex = 0;
UInt32 digestIndex;
Byte allDigestsDefined = 0;
Byte isDirMask = 0;
Byte crcMask = 0;
Byte mask = 0x80;
MY_ALLOC(UInt32, p->FolderToFile, p->db.NumFolders + 1, allocMain);
MY_ALLOC_ZE(UInt32, p->FileToFolder, p->NumFiles, allocMain);
MY_ALLOC(UInt64, p->UnpackPositions, p->NumFiles + 1, allocMain);
MY_ALLOC_ZE(Byte, p->IsDirs, (p->NumFiles + 7) >> 3, allocMain);
RINOK(SzBitUi32s_Alloc(&p->CRCs, p->NumFiles, allocMain));
if (ssi.sdCRCs.Size != 0)
{
SZ_READ_BYTE_SD(&ssi.sdCRCs, allDigestsDefined);
if (allDigestsDefined)
digestsVals = ssi.sdCRCs.Data;
else
{
size_t numBytes = (ssi.NumSubDigests + 7) >> 3;
digestsDefs = ssi.sdCRCs.Data;
digestsVals = digestsDefs + numBytes;
}
}
digestIndex = 0;
for (i = 0; i < numFiles; i++, mask >>= 1)
{
if (mask == 0)
{
UInt32 byteIndex = (i - 1) >> 3;
p->IsDirs[byteIndex] = isDirMask;
p->CRCs.Defs[byteIndex] = crcMask;
isDirMask = 0;
crcMask = 0;
mask = 0x80;
}
p->UnpackPositions[i] = unpackPos;
p->CRCs.Vals[i] = 0;
if (emptyStreams && SzBitArray_Check(emptyStreams, i))
{
if (emptyFiles)
{
if (!SzBitArray_Check(emptyFiles, emptyFileIndex))
isDirMask |= mask;
emptyFileIndex++;
}
else
isDirMask |= mask;
if (remSubStreams == 0)
{
p->FileToFolder[i] = (UInt32)-1;
continue;
}
}
if (remSubStreams == 0)
{
for (;;)
{
if (folderIndex >= p->db.NumFolders)
return SZ_ERROR_ARCHIVE;
p->FolderToFile[folderIndex] = i;
numSubStreams = 1;
if (ssi.sdNumSubStreams.Data)
{
RINOK(SzReadNumber32(&ssi.sdNumSubStreams, &numSubStreams));
}
remSubStreams = numSubStreams;
if (numSubStreams != 0)
break;
{
UInt64 folderUnpackSize = SzAr_GetFolderUnpackSize(&p->db, folderIndex);
unpackPos += folderUnpackSize;
if (unpackPos < folderUnpackSize)
return SZ_ERROR_ARCHIVE;
}
folderIndex++;
}
}
p->FileToFolder[i] = folderIndex;
if (emptyStreams && SzBitArray_Check(emptyStreams, i))
continue;
if (--remSubStreams == 0)
{
UInt64 folderUnpackSize = SzAr_GetFolderUnpackSize(&p->db, folderIndex);
UInt64 startFolderUnpackPos = p->UnpackPositions[p->FolderToFile[folderIndex]];
if (folderUnpackSize < unpackPos - startFolderUnpackPos)
return SZ_ERROR_ARCHIVE;
unpackPos = startFolderUnpackPos + folderUnpackSize;
if (unpackPos < folderUnpackSize)
return SZ_ERROR_ARCHIVE;
if (numSubStreams == 1 && SzBitWithVals_Check(&p->db.FolderCRCs, i))
{
p->CRCs.Vals[i] = p->db.FolderCRCs.Vals[folderIndex];
crcMask |= mask;
}
else if (allDigestsDefined || (digestsDefs && SzBitArray_Check(digestsDefs, digestIndex)))
{
p->CRCs.Vals[i] = GetUi32(digestsVals + (size_t)digestsValsIndex * 4);
digestsValsIndex++;
crcMask |= mask;
}
folderIndex++;
}
else
{
UInt64 v;
RINOK(ReadNumber(&ssi.sdSizes, &v));
unpackPos += v;
if (unpackPos < v)
return SZ_ERROR_ARCHIVE;
if (allDigestsDefined || (digestsDefs && SzBitArray_Check(digestsDefs, digestIndex)))
{
p->CRCs.Vals[i] = GetUi32(digestsVals + (size_t)digestsValsIndex * 4);
digestsValsIndex++;
crcMask |= mask;
}
}
}
if (mask != 0x80)
{
UInt32 byteIndex = (i - 1) >> 3;
p->IsDirs[byteIndex] = isDirMask;
p->CRCs.Defs[byteIndex] = crcMask;
}
p->UnpackPositions[i] = unpackPos;
if (remSubStreams != 0)
return SZ_ERROR_ARCHIVE;
for (;;)
{
p->FolderToFile[folderIndex] = i;
if (folderIndex >= p->db.NumFolders)
break;
if (!ssi.sdNumSubStreams.Data)
return SZ_ERROR_ARCHIVE;
RINOK(SzReadNumber32(&ssi.sdNumSubStreams, &numSubStreams));
if (numSubStreams != 0)
return SZ_ERROR_ARCHIVE;
/*
{
UInt64 folderUnpackSize = SzAr_GetFolderUnpackSize(&p->db, folderIndex);
unpackPos += folderUnpackSize;
if (unpackPos < folderUnpackSize)
return SZ_ERROR_ARCHIVE;
}
*/
folderIndex++;
}
if (ssi.sdNumSubStreams.Data && ssi.sdNumSubStreams.Size != 0)
return SZ_ERROR_ARCHIVE;
}
return SZ_OK;
}