This commit is contained in:
Igor Pavlov
2015-11-20 00:00:00 +00:00
committed by Kornel Lesiński
parent e24f7fba53
commit 5de23c1deb
17 changed files with 363 additions and 394 deletions

82
C/7z.h
View File

@@ -1,5 +1,5 @@
/* 7z.h -- 7z interface /* 7z.h -- 7z interface
2014-02-08 : Igor Pavlov : Public domain */ 2015-11-18 : Igor Pavlov : Public domain */
#ifndef __7Z_H #ifndef __7Z_H
#define __7Z_H #define __7Z_H
@@ -48,21 +48,10 @@ typedef struct
UInt32 PackStreams[SZ_NUM_PACK_STREAMS_IN_FOLDER_MAX]; UInt32 PackStreams[SZ_NUM_PACK_STREAMS_IN_FOLDER_MAX];
CSzBond Bonds[SZ_NUM_BONDS_IN_FOLDER_MAX]; CSzBond Bonds[SZ_NUM_BONDS_IN_FOLDER_MAX];
CSzCoderInfo Coders[SZ_NUM_CODERS_IN_FOLDER_MAX]; CSzCoderInfo Coders[SZ_NUM_CODERS_IN_FOLDER_MAX];
UInt64 CodersUnpackSizes[SZ_NUM_CODERS_IN_FOLDER_MAX];
} CSzFolder; } CSzFolder;
/*
typedef struct
{
size_t CodersDataOffset;
size_t UnpackSizeDataOffset;
// UInt32 StartCoderUnpackSizesIndex;
UInt32 StartPackStreamIndex;
// UInt32 IndexOfMainOutStream;
} CSzFolder2;
*/
SRes SzGetNextFolderItem(CSzFolder *f, CSzData *sd, CSzData *sdSizes); SRes SzGetNextFolderItem(CSzFolder *f, CSzData *sd);
typedef struct typedef struct
{ {
@@ -92,47 +81,25 @@ typedef struct
UInt32 NumPackStreams; UInt32 NumPackStreams;
UInt32 NumFolders; UInt32 NumFolders;
UInt64 *PackPositions; // NumPackStreams + 1 UInt64 *PackPositions; // NumPackStreams + 1
CSzBitUi32s FolderCRCs; CSzBitUi32s FolderCRCs; // NumFolders
size_t *FoCodersOffsets; size_t *FoCodersOffsets; // NumFolders + 1
size_t *FoSizesOffsets; UInt32 *FoStartPackStreamIndex; // NumFolders + 1
// UInt32 StartCoderUnpackSizesIndex; UInt32 *FoToCoderUnpackSizes; // NumFolders + 1
UInt32 *FoStartPackStreamIndex; Byte *FoToMainUnpackSizeIndex; // NumFolders
UInt64 *CoderUnpackSizes; // for all coders in all folders
// CSzFolder2 *Folders; // +1 item for sum values
Byte *CodersData; Byte *CodersData;
Byte *UnpackSizesData;
size_t UnpackSizesDataSize;
// UInt64 *CoderUnpackSizes;
} CSzAr; } CSzAr;
UInt64 SzAr_GetFolderUnpackSize(const CSzAr *p, UInt32 folderIndex);
SRes SzAr_DecodeFolder(const CSzAr *p, UInt32 folderIndex, SRes SzAr_DecodeFolder(const CSzAr *p, UInt32 folderIndex,
ILookInStream *stream, UInt64 startPos, ILookInStream *stream, UInt64 startPos,
Byte *outBuffer, size_t outSize, Byte *outBuffer, size_t outSize,
ISzAlloc *allocMain); ISzAlloc *allocMain);
/*
SzExtract extracts file from archive
*outBuffer must be 0 before first call for each new archive.
Extracting cache:
If you need to decompress more than one file, you can send
these values from previous call:
*blockIndex,
*outBuffer,
*outBufferSize
You can consider "*outBuffer" as cache of solid block. If your archive is solid,
it will increase decompression speed.
If you use external function, you can declare these 3 cache variables
(blockIndex, outBuffer, outBufferSize) as static in that external function.
Free *outBuffer and set *outBuffer to 0, if you want to flush cache.
*/
typedef struct typedef struct
{ {
CSzAr db; CSzAr db;
@@ -142,7 +109,7 @@ typedef struct
UInt32 NumFiles; UInt32 NumFiles;
UInt64 *UnpackPositions; UInt64 *UnpackPositions; // NumFiles + 1
// Byte *IsEmptyFiles; // Byte *IsEmptyFiles;
Byte *IsDirs; Byte *IsDirs;
CSzBitUi32s CRCs; CSzBitUi32s CRCs;
@@ -152,9 +119,8 @@ typedef struct
CSzBitUi64s MTime; CSzBitUi64s MTime;
CSzBitUi64s CTime; CSzBitUi64s CTime;
// UInt32 *FolderStartPackStreamIndex; UInt32 *FolderToFile; // NumFolders + 1
UInt32 *FolderStartFileIndex; // + 1 UInt32 *FileToFolder; // NumFiles
UInt32 *FileIndexToFolderIndexMap;
size_t *FileNameOffsets; /* in 2-byte steps */ size_t *FileNameOffsets; /* in 2-byte steps */
Byte *FileNames; /* UTF-16-LE */ Byte *FileNames; /* UTF-16-LE */
@@ -182,6 +148,28 @@ size_t SzArEx_GetFullNameLen(const CSzArEx *p, size_t fileIndex);
UInt16 *SzArEx_GetFullNameUtf16_Back(const CSzArEx *p, size_t fileIndex, UInt16 *dest); UInt16 *SzArEx_GetFullNameUtf16_Back(const CSzArEx *p, size_t fileIndex, UInt16 *dest);
*/ */
/*
SzArEx_Extract extracts file from archive
*outBuffer must be 0 before first call for each new archive.
Extracting cache:
If you need to decompress more than one file, you can send
these values from previous call:
*blockIndex,
*outBuffer,
*outBufferSize
You can consider "*outBuffer" as cache of solid block. If your archive is solid,
it will increase decompression speed.
If you use external function, you can declare these 3 cache variables
(blockIndex, outBuffer, outBufferSize) as static in that external function.
Free *outBuffer and set *outBuffer to 0, if you want to flush cache.
*/
SRes SzArEx_Extract( SRes SzArEx_Extract(
const CSzArEx *db, const CSzArEx *db,
ILookInStream *inStream, ILookInStream *inStream,

View File

@@ -1,5 +1,5 @@
/* 7zArcIn.c -- 7z Input functions /* 7zArcIn.c -- 7z Input functions
2015-11-13 : Igor Pavlov : Public domain */ 2015-11-18 : Igor Pavlov : Public domain */
#include "Precomp.h" #include "Precomp.h"
@@ -11,15 +11,15 @@
#include "CpuArch.h" #include "CpuArch.h"
#define MY_ALLOC(T, p, size, alloc) { \ #define MY_ALLOC(T, p, size, alloc) { \
if ((p = (T *)IAlloc_Alloc(alloc, (size) * sizeof(T))) == 0) return SZ_ERROR_MEM; } if ((p = (T *)IAlloc_Alloc(alloc, (size) * sizeof(T))) == NULL) return SZ_ERROR_MEM; }
#define MY_ALLOC_ZE(T, p, size, alloc) { if ((size) == 0) p = 0; else MY_ALLOC(T, p, size, alloc) } #define MY_ALLOC_ZE(T, p, size, alloc) { if ((size) == 0) p = NULL; else MY_ALLOC(T, p, size, alloc) }
#define MY_ALLOC_AND_CPY(to, size, from, alloc) \ #define MY_ALLOC_AND_CPY(to, size, from, alloc) \
{ MY_ALLOC(Byte, to, size, alloc); memcpy(to, from, size); } { MY_ALLOC(Byte, to, size, alloc); memcpy(to, from, size); }
#define MY_ALLOC_ZE_AND_CPY(to, size, from, alloc) \ #define MY_ALLOC_ZE_AND_CPY(to, size, from, alloc) \
{ if ((size) == 0) p = 0; else { MY_ALLOC_AND_CPY(to, size, from, alloc) } } { if ((size) == 0) p = NULL; else { MY_ALLOC_AND_CPY(to, size, from, alloc) } }
#define k7zMajorVersion 0 #define k7zMajorVersion 0
@@ -58,26 +58,14 @@ enum EIdEnum
const Byte k7zSignature[k7zSignatureSize] = {'7', 'z', 0xBC, 0xAF, 0x27, 0x1C}; const Byte k7zSignature[k7zSignatureSize] = {'7', 'z', 0xBC, 0xAF, 0x27, 0x1C};
#define SzBitUi32s_Init(p) { (p)->Defs = NULL; (p)->Vals = NULL; }
/*
static int SzFolder_FindBondForInStream(const CSzFolder *p, UInt32 inStreamIndex)
{
UInt32 i;
for (i = 0; i < p->NumBonds; i++)
if (p->Bonds[i].InIndex == inStreamIndex)
return i;
return -1;
}
*/
#define SzBitUi32s_Init(p) { (p)->Defs = 0; (p)->Vals = 0; }
static SRes SzBitUi32s_Alloc(CSzBitUi32s *p, size_t num, ISzAlloc *alloc) static SRes SzBitUi32s_Alloc(CSzBitUi32s *p, size_t num, ISzAlloc *alloc)
{ {
if (num == 0) if (num == 0)
{ {
p->Defs = 0; p->Defs = NULL;
p->Vals = 0; p->Vals = NULL;
} }
else else
{ {
@@ -89,48 +77,48 @@ static SRes SzBitUi32s_Alloc(CSzBitUi32s *p, size_t num, ISzAlloc *alloc)
void SzBitUi32s_Free(CSzBitUi32s *p, ISzAlloc *alloc) void SzBitUi32s_Free(CSzBitUi32s *p, ISzAlloc *alloc)
{ {
IAlloc_Free(alloc, p->Defs); p->Defs = 0; IAlloc_Free(alloc, p->Defs); p->Defs = NULL;
IAlloc_Free(alloc, p->Vals); p->Vals = 0; IAlloc_Free(alloc, p->Vals); p->Vals = NULL;
} }
#define SzBitUi64s_Init(p) { (p)->Defs = 0; (p)->Vals = 0; } #define SzBitUi64s_Init(p) { (p)->Defs = NULL; (p)->Vals = NULL; }
void SzBitUi64s_Free(CSzBitUi64s *p, ISzAlloc *alloc) void SzBitUi64s_Free(CSzBitUi64s *p, ISzAlloc *alloc)
{ {
IAlloc_Free(alloc, p->Defs); p->Defs = 0; IAlloc_Free(alloc, p->Defs); p->Defs = NULL;
IAlloc_Free(alloc, p->Vals); p->Vals = 0; IAlloc_Free(alloc, p->Vals); p->Vals = NULL;
} }
static void SzAr_Init(CSzAr *p) static void SzAr_Init(CSzAr *p)
{ {
p->NumPackStreams = 0; p->NumPackStreams = 0;
p->NumFolders = 0; p->NumFolders = 0;
p->PackPositions = 0;
p->PackPositions = NULL;
SzBitUi32s_Init(&p->FolderCRCs); SzBitUi32s_Init(&p->FolderCRCs);
// p->Folders = 0;
p->FoCodersOffsets = 0;
p->FoSizesOffsets = 0;
p->FoStartPackStreamIndex = 0;
p->CodersData = 0; p->FoCodersOffsets = NULL;
// p->CoderUnpackSizes = 0; p->FoStartPackStreamIndex = NULL;
p->UnpackSizesData = 0; p->FoToCoderUnpackSizes = NULL;
p->FoToMainUnpackSizeIndex = NULL;
p->CoderUnpackSizes = NULL;
p->CodersData = NULL;
} }
static void SzAr_Free(CSzAr *p, ISzAlloc *alloc) static void SzAr_Free(CSzAr *p, ISzAlloc *alloc)
{ {
IAlloc_Free(alloc, p->UnpackSizesData);
IAlloc_Free(alloc, p->CodersData);
// IAlloc_Free(alloc, p->CoderUnpackSizes);
IAlloc_Free(alloc, p->PackPositions); IAlloc_Free(alloc, p->PackPositions);
// IAlloc_Free(alloc, p->Folders);
IAlloc_Free(alloc, p->FoCodersOffsets);
IAlloc_Free(alloc, p->FoSizesOffsets);
IAlloc_Free(alloc, p->FoStartPackStreamIndex);
SzBitUi32s_Free(&p->FolderCRCs, alloc); SzBitUi32s_Free(&p->FolderCRCs, alloc);
IAlloc_Free(alloc, p->FoCodersOffsets);
IAlloc_Free(alloc, p->FoStartPackStreamIndex);
IAlloc_Free(alloc, p->FoToCoderUnpackSizes);
IAlloc_Free(alloc, p->FoToMainUnpackSizeIndex);
IAlloc_Free(alloc, p->CoderUnpackSizes);
IAlloc_Free(alloc, p->CodersData);
SzAr_Init(p); SzAr_Init(p);
} }
@@ -139,18 +127,19 @@ static void SzAr_Free(CSzAr *p, ISzAlloc *alloc)
void SzArEx_Init(CSzArEx *p) void SzArEx_Init(CSzArEx *p)
{ {
SzAr_Init(&p->db); SzAr_Init(&p->db);
p->NumFiles = 0; p->NumFiles = 0;
p->dataPos = 0; p->dataPos = 0;
// p->Files = 0;
p->UnpackPositions = 0; p->UnpackPositions = NULL;
// p->IsEmptyFiles = 0; p->IsDirs = NULL;
p->IsDirs = 0;
// p->FolderStartPackStreamIndex = 0; p->FolderToFile = NULL;
// p->PackStreamStartPositions = 0; p->FileToFolder = NULL;
p->FolderStartFileIndex = 0;
p->FileIndexToFolderIndexMap = 0; p->FileNameOffsets = NULL;
p->FileNameOffsets = 0; p->FileNames = NULL;
p->FileNames = 0;
SzBitUi32s_Init(&p->CRCs); SzBitUi32s_Init(&p->CRCs);
SzBitUi32s_Init(&p->Attribs); SzBitUi32s_Init(&p->Attribs);
// SzBitUi32s_Init(&p->Parents); // SzBitUi32s_Init(&p->Parents);
@@ -160,29 +149,27 @@ void SzArEx_Init(CSzArEx *p)
void SzArEx_Free(CSzArEx *p, ISzAlloc *alloc) void SzArEx_Free(CSzArEx *p, ISzAlloc *alloc)
{ {
// IAlloc_Free(alloc, p->FolderStartPackStreamIndex); IAlloc_Free(alloc, p->UnpackPositions);
// IAlloc_Free(alloc, p->PackStreamStartPositions); IAlloc_Free(alloc, p->IsDirs);
IAlloc_Free(alloc, p->FolderStartFileIndex);
IAlloc_Free(alloc, p->FileIndexToFolderIndexMap); IAlloc_Free(alloc, p->FolderToFile);
IAlloc_Free(alloc, p->FileToFolder);
IAlloc_Free(alloc, p->FileNameOffsets); IAlloc_Free(alloc, p->FileNameOffsets);
IAlloc_Free(alloc, p->FileNames); IAlloc_Free(alloc, p->FileNames);
SzBitUi64s_Free(&p->CTime, alloc);
SzBitUi64s_Free(&p->MTime, alloc);
SzBitUi32s_Free(&p->CRCs, alloc); SzBitUi32s_Free(&p->CRCs, alloc);
// SzBitUi32s_Free(&p->Parents, alloc);
SzBitUi32s_Free(&p->Attribs, alloc); SzBitUi32s_Free(&p->Attribs, alloc);
IAlloc_Free(alloc, p->IsDirs); // SzBitUi32s_Free(&p->Parents, alloc);
// IAlloc_Free(alloc, p->IsEmptyFiles); SzBitUi64s_Free(&p->MTime, alloc);
IAlloc_Free(alloc, p->UnpackPositions); SzBitUi64s_Free(&p->CTime, alloc);
// IAlloc_Free(alloc, p->Files);
SzAr_Free(&p->db, alloc); SzAr_Free(&p->db, alloc);
SzArEx_Init(p); SzArEx_Init(p);
} }
static int TestSignatureCandidate(Byte *testBytes)
static int TestSignatureCandidate(const Byte *testBytes)
{ {
unsigned i; unsigned i;
for (i = 0; i < k7zSignatureSize; i++) for (i = 0; i < k7zSignatureSize; i++)
@@ -191,16 +178,7 @@ static int TestSignatureCandidate(Byte *testBytes)
return 1; return 1;
} }
#define SzData_Clear(p) { (p)->Data = 0; (p)->Size = 0; } #define SzData_Clear(p) { (p)->Data = NULL; (p)->Size = 0; }
static SRes SzReadByte(CSzData *sd, Byte *b)
{
if (sd->Size == 0)
return SZ_ERROR_ARCHIVE;
sd->Size--;
*b = *sd->Data++;
return SZ_OK;
}
#define SZ_READ_BYTE_SD(_sd_, dest) if ((_sd_)->Size == 0) return SZ_ERROR_ARCHIVE; (_sd_)->Size--; dest = *(_sd_)->Data++; #define SZ_READ_BYTE_SD(_sd_, dest) if ((_sd_)->Size == 0) return SZ_ERROR_ARCHIVE; (_sd_)->Size--; dest = *(_sd_)->Data++;
#define SZ_READ_BYTE(dest) SZ_READ_BYTE_SD(sd, dest) #define SZ_READ_BYTE(dest) SZ_READ_BYTE_SD(sd, dest)
@@ -249,57 +227,6 @@ static MY_NO_INLINE SRes ReadNumber(CSzData *sd, UInt64 *value)
return SZ_OK; return SZ_OK;
} }
/*
static MY_NO_INLINE const Byte *SzReadNumbers(const Byte *data, const Byte *dataLim, UInt64 *values, UInt32 num)
{
for (; num != 0; num--)
{
Byte firstByte;
Byte mask;
unsigned i;
UInt32 v;
UInt64 value;
if (data == dataLim)
return NULL;
firstByte = *data++;
if ((firstByte & 0x80) == 0)
{
*values++ = firstByte;
continue;
}
if (data == dataLim)
return NULL;
v = *data++;
if ((firstByte & 0x40) == 0)
{
*values++ = (((UInt32)firstByte & 0x3F) << 8) | v;
continue;
}
if (data == dataLim)
return NULL;
value = v | ((UInt32)*data++ << 8);
mask = 0x20;
for (i = 2; i < 8; i++)
{
if ((firstByte & mask) == 0)
{
UInt64 highPart = firstByte & (mask - 1);
value |= (highPart << (8 * i));
break;
}
if (data == dataLim)
return NULL;
value |= ((UInt64)*data++ << (8 * i));
mask >>= 1;
}
*values++ = value;
}
return data;
}
*/
static MY_NO_INLINE SRes SzReadNumber32(CSzData *sd, UInt32 *value) static MY_NO_INLINE SRes SzReadNumber32(CSzData *sd, UInt32 *value)
{ {
@@ -336,7 +263,7 @@ static SRes SkipData(CSzData *sd)
return SZ_OK; return SZ_OK;
} }
static SRes WaitId(CSzData *sd, UInt64 id) static SRes WaitId(CSzData *sd, UInt32 id)
{ {
for (;;) for (;;)
{ {
@@ -375,7 +302,7 @@ static UInt32 CountDefinedBits(const Byte *bits, UInt32 numItems)
m--; m--;
sum += ((b >> m) & 1); sum += ((b >> m) & 1);
} }
return sum ; return sum;
} }
static MY_NO_INLINE SRes ReadBitVector(CSzData *sd, UInt32 numItems, Byte **v, ISzAlloc *alloc) static MY_NO_INLINE SRes ReadBitVector(CSzData *sd, UInt32 numItems, Byte **v, ISzAlloc *alloc)
@@ -384,7 +311,7 @@ static MY_NO_INLINE SRes ReadBitVector(CSzData *sd, UInt32 numItems, Byte **v, I
Byte *v2; Byte *v2;
UInt32 numBytes = (numItems + 7) >> 3; UInt32 numBytes = (numItems + 7) >> 3;
*v = NULL; *v = NULL;
RINOK(SzReadByte(sd, &allAreDefined)); SZ_READ_BYTE(allAreDefined);
if (numBytes == 0) if (numBytes == 0)
return SZ_OK; return SZ_OK;
if (allAreDefined == 0) if (allAreDefined == 0)
@@ -438,7 +365,7 @@ static SRes SkipBitUi32s(CSzData *sd, UInt32 numItems)
{ {
Byte allAreDefined; Byte allAreDefined;
UInt32 numDefined = numItems; UInt32 numDefined = numItems;
RINOK(SzReadByte(sd, &allAreDefined)); SZ_READ_BYTE(allAreDefined);
if (!allAreDefined) if (!allAreDefined)
{ {
size_t numBytes = (numItems + 7) >> 3; size_t numBytes = (numItems + 7) >> 3;
@@ -502,7 +429,7 @@ static SRes SzReadSwitch(CSzData *sd)
#define k_NumCodersStreams_in_Folder_MAX (SZ_NUM_BONDS_IN_FOLDER_MAX + SZ_NUM_PACK_STREAMS_IN_FOLDER_MAX) #define k_NumCodersStreams_in_Folder_MAX (SZ_NUM_BONDS_IN_FOLDER_MAX + SZ_NUM_PACK_STREAMS_IN_FOLDER_MAX)
SRes SzGetNextFolderItem(CSzFolder *f, CSzData *sd, CSzData *sdSizes) SRes SzGetNextFolderItem(CSzFolder *f, CSzData *sd)
{ {
UInt32 numCoders, i; UInt32 numCoders, i;
UInt32 numInStreams = 0; UInt32 numInStreams = 0;
@@ -524,7 +451,7 @@ SRes SzGetNextFolderItem(CSzFolder *f, CSzData *sd, CSzData *sdSizes)
unsigned idSize, j; unsigned idSize, j;
UInt64 id; UInt64 id;
RINOK(SzReadByte(sd, &mainByte)); SZ_READ_BYTE(mainByte);
if ((mainByte & 0xC0) != 0) if ((mainByte & 0xC0) != 0)
return SZ_ERROR_UNSUPPORTED; return SZ_ERROR_UNSUPPORTED;
@@ -663,16 +590,12 @@ SRes SzGetNextFolderItem(CSzFolder *f, CSzData *sd, CSzData *sdSizes)
} }
} }
for (i = 0; i < numCoders; i++)
{
RINOK(ReadNumber(sdSizes, f->CodersUnpackSizes + i));
}
f->NumCoders = numCoders; f->NumCoders = numCoders;
return SZ_OK; return SZ_OK;
} }
static MY_NO_INLINE SRes SkipNumbers(CSzData *sd2, UInt32 num) static MY_NO_INLINE SRes SkipNumbers(CSzData *sd2, UInt32 num)
{ {
CSzData sd; CSzData sd;
@@ -703,9 +626,11 @@ static MY_NO_INLINE SRes SkipNumbers(CSzData *sd2, UInt32 num)
return SZ_OK; return SZ_OK;
} }
#define k_Scan_NumCoders_MAX 64 #define k_Scan_NumCoders_MAX 64
#define k_Scan_NumCodersStreams_in_Folder_MAX 64 #define k_Scan_NumCodersStreams_in_Folder_MAX 64
static SRes ReadUnpackInfo(CSzAr *p, static SRes ReadUnpackInfo(CSzAr *p,
CSzData *sd2, CSzData *sd2,
UInt32 numFoldersMax, UInt32 numFoldersMax,
@@ -739,8 +664,9 @@ static SRes ReadUnpackInfo(CSzAr *p,
} }
MY_ALLOC(size_t, p->FoCodersOffsets, (size_t)numFolders + 1, alloc); MY_ALLOC(size_t, p->FoCodersOffsets, (size_t)numFolders + 1, alloc);
MY_ALLOC(size_t, p->FoSizesOffsets, (size_t)numFolders + 1, alloc);
MY_ALLOC(UInt32, p->FoStartPackStreamIndex, (size_t)numFolders + 1, alloc); MY_ALLOC(UInt32, p->FoStartPackStreamIndex, (size_t)numFolders + 1, alloc);
MY_ALLOC(UInt32, p->FoToCoderUnpackSizes, (size_t)numFolders + 1, alloc);
MY_ALLOC(Byte, p->FoToMainUnpackSizeIndex, (size_t)numFolders, alloc);
startBufPtr = sd.Data; startBufPtr = sd.Data;
@@ -857,7 +783,8 @@ static SRes ReadUnpackInfo(CSzAr *p,
} }
p->FoStartPackStreamIndex[fo] = packStreamIndex; p->FoStartPackStreamIndex[fo] = packStreamIndex;
p->FoSizesOffsets[fo] = (numCoders << 8) | indexOfMainStream; p->FoToCoderUnpackSizes[fo] = numCodersOutStreams;
p->FoToMainUnpackSizeIndex[fo] = (Byte)indexOfMainStream;
numCodersOutStreams += numCoders; numCodersOutStreams += numCoders;
if (numCodersOutStreams < numCoders) if (numCodersOutStreams < numCoders)
return SZ_ERROR_UNSUPPORTED; return SZ_ERROR_UNSUPPORTED;
@@ -870,6 +797,8 @@ static SRes ReadUnpackInfo(CSzAr *p,
return SZ_ERROR_ARCHIVE; return SZ_ERROR_ARCHIVE;
} }
} }
p->FoToCoderUnpackSizes[fo] = numCodersOutStreams;
{ {
size_t dataSize = sd.Data - startBufPtr; size_t dataSize = sd.Data - startBufPtr;
@@ -887,27 +816,13 @@ static SRes ReadUnpackInfo(CSzAr *p,
RINOK(WaitId(&sd, k7zIdCodersUnpackSize)); RINOK(WaitId(&sd, k7zIdCodersUnpackSize));
// MY_ALLOC_ZE(UInt64, p->CoderUnpackSizes, (size_t)numCodersOutStreams, alloc); MY_ALLOC_ZE(UInt64, p->CoderUnpackSizes, (size_t)numCodersOutStreams, alloc);
{ {
size_t dataSize = sd.Size;
/*
UInt32 i; UInt32 i;
for (i = 0; i < numCodersOutStreams; i++) for (i = 0; i < numCodersOutStreams; i++)
{ {
RINOK(ReadNumber(&sd, p->CoderUnpackSizes + i)); RINOK(ReadNumber(&sd, p->CoderUnpackSizes + i));
} }
*/
RINOK(SkipNumbers(&sd, numCodersOutStreams));
dataSize -= sd.Size;
MY_ALLOC_ZE_AND_CPY(p->UnpackSizesData, dataSize, sd.Data - dataSize, alloc);
p->UnpackSizesDataSize = dataSize;
/*
const Byte *data = SzReadNumbers(sd.Data, sd.Data + sd.Size, p->CoderUnpackSizes, numCodersOutStreams);
if (data == NULL)
return SZ_ERROR_ARCHIVE;
sd.Size = sd.Data + sd.Size - data;
sd.Data = data;
*/
} }
for (;;) for (;;)
@@ -928,6 +843,13 @@ static SRes ReadUnpackInfo(CSzAr *p,
} }
} }
UInt64 SzAr_GetFolderUnpackSize(const CSzAr *p, UInt32 folderIndex)
{
return p->CoderUnpackSizes[p->FoToCoderUnpackSizes[folderIndex] + p->FoToMainUnpackSizeIndex[folderIndex]];
}
typedef struct typedef struct
{ {
UInt32 NumTotalSubStreams; UInt32 NumTotalSubStreams;
@@ -937,7 +859,6 @@ typedef struct
CSzData sdCRCs; CSzData sdCRCs;
} CSubStreamInfo; } CSubStreamInfo;
#define SzUi32IndexMax (((UInt32)1 << 31) - 2)
static SRes ReadSubStreamsInfo(CSzAr *p, CSzData *sd, CSubStreamInfo *ssi) static SRes ReadSubStreamsInfo(CSzAr *p, CSzData *sd, CSubStreamInfo *ssi)
{ {
@@ -1064,7 +985,6 @@ static SRes SzReadAndDecodePackedStreams(
UInt64 dataStartPos; UInt64 dataStartPos;
UInt32 fo; UInt32 fo;
CSubStreamInfo ssi; CSubStreamInfo ssi;
CSzData sdCodersUnpSizes;
RINOK(SzReadStreamsInfo(p, sd, numFoldersMax, NULL, 0, &dataStartPos, &ssi, allocTemp)); RINOK(SzReadStreamsInfo(p, sd, numFoldersMax, NULL, 0, &dataStartPos, &ssi, allocTemp));
@@ -1072,51 +992,24 @@ static SRes SzReadAndDecodePackedStreams(
if (p->NumFolders == 0) if (p->NumFolders == 0)
return SZ_ERROR_ARCHIVE; return SZ_ERROR_ARCHIVE;
sdCodersUnpSizes.Data = p->UnpackSizesData;
sdCodersUnpSizes.Size = p->UnpackSizesDataSize;
for (fo = 0; fo < p->NumFolders; fo++) for (fo = 0; fo < p->NumFolders; fo++)
Buf_Init(tempBufs + fo); Buf_Init(tempBufs + fo);
for (fo = 0; fo < p->NumFolders; fo++) for (fo = 0; fo < p->NumFolders; fo++)
{ {
CBuf *tempBuf = tempBufs + fo; CBuf *tempBuf = tempBufs + fo;
// folder = p->Folders; UInt64 unpackSize = SzAr_GetFolderUnpackSize(p, fo);
// unpackSize = SzAr_GetFolderUnpackSize(p, 0);
UInt32 mix = (UInt32)p->FoSizesOffsets[fo];
UInt32 mainIndex = mix & 0xFF;
UInt32 numOutStreams = mix >> 8;
UInt32 si;
UInt64 unpackSize = 0;
p->FoSizesOffsets[fo] = sdCodersUnpSizes.Data - p->UnpackSizesData;
for (si = 0; si < numOutStreams; si++)
{
UInt64 curSize;
RINOK(ReadNumber(&sdCodersUnpSizes, &curSize));
if (si == mainIndex)
{
unpackSize = curSize;
break;
}
}
if (si == numOutStreams)
return SZ_ERROR_FAIL;
if ((size_t)unpackSize != unpackSize) if ((size_t)unpackSize != unpackSize)
return SZ_ERROR_MEM; return SZ_ERROR_MEM;
if (!Buf_Create(tempBuf, (size_t)unpackSize, allocTemp)) if (!Buf_Create(tempBuf, (size_t)unpackSize, allocTemp))
return SZ_ERROR_MEM; return SZ_ERROR_MEM;
} }
p->FoSizesOffsets[fo] = sdCodersUnpSizes.Data - p->UnpackSizesData;
for (fo = 0; fo < p->NumFolders; fo++) for (fo = 0; fo < p->NumFolders; fo++)
{ {
const CBuf *tempBuf = tempBufs + fo; const CBuf *tempBuf = tempBufs + fo;
RINOK(LookInStream_SeekTo(inStream, dataStartPos)); RINOK(LookInStream_SeekTo(inStream, dataStartPos));
RINOK(SzAr_DecodeFolder(p, fo, inStream, dataStartPos, tempBuf->data, tempBuf->size, allocTemp)); RINOK(SzAr_DecodeFolder(p, fo, inStream, dataStartPos, tempBuf->data, tempBuf->size, allocTemp));
if (SzBitWithVals_Check(&p->FolderCRCs, fo))
if (CrcCalc(tempBuf->data, tempBuf->size) != p->FolderCRCs.Vals[fo])
return SZ_ERROR_CRC;
} }
return SZ_OK; return SZ_OK;
@@ -1164,7 +1057,7 @@ static MY_NO_INLINE SRes ReadTime(CSzBitUi64s *p, UInt32 num,
RINOK(ReadBitVector(sd2, num, &p->Defs, alloc)); RINOK(ReadBitVector(sd2, num, &p->Defs, alloc));
RINOK(SzReadByte(sd2, &external)); SZ_READ_BYTE_SD(sd2, external);
if (external == 0) if (external == 0)
sd = *sd2; sd = *sd2;
else else
@@ -1198,14 +1091,13 @@ static MY_NO_INLINE SRes ReadTime(CSzBitUi64s *p, UInt32 num,
return SZ_OK; return SZ_OK;
} }
#define NUM_ADDITIONAL_STREAMS_MAX 8 #define NUM_ADDITIONAL_STREAMS_MAX 8
static SRes SzReadHeader2( static SRes SzReadHeader2(
CSzArEx *p, /* allocMain */ CSzArEx *p, /* allocMain */
CSzData *sd, CSzData *sd,
// Byte **emptyStreamVector, /* allocTemp */
// Byte **emptyFileVector, /* allocTemp */
// Byte **lwtVector, /* allocTemp */
ILookInStream *inStream, ILookInStream *inStream,
CBuf *tempBufs, UInt32 *numTempBufs, CBuf *tempBufs, UInt32 *numTempBufs,
ISzAlloc *allocMain, ISzAlloc *allocMain,
@@ -1216,8 +1108,8 @@ static SRes SzReadHeader2(
UInt32 numFiles = 0; UInt32 numFiles = 0;
UInt32 numEmptyStreams = 0; UInt32 numEmptyStreams = 0;
CSubStreamInfo ssi; CSubStreamInfo ssi;
const Byte *emptyStreams = 0; const Byte *emptyStreams = NULL;
const Byte *emptyFiles = 0; const Byte *emptyFiles = NULL;
SzData_Clear(&ssi.sdSizes); SzData_Clear(&ssi.sdSizes);
SzData_Clear(&ssi.sdCRCs); SzData_Clear(&ssi.sdCRCs);
@@ -1241,22 +1133,19 @@ static SRes SzReadHeader2(
RINOK(ReadID(sd, &type)); RINOK(ReadID(sd, &type));
} }
// if (type == k7zIdAdditionalStreamsInfo) return SZ_ERROR_UNSUPPORTED;
if (type == k7zIdAdditionalStreamsInfo) if (type == k7zIdAdditionalStreamsInfo)
{ {
CSzAr tempAr; CSzAr tempAr;
SRes res; SRes res;
UInt32 numTempFolders;
SzAr_Init(&tempAr); SzAr_Init(&tempAr);
res = SzReadAndDecodePackedStreams(inStream, sd, tempBufs, NUM_ADDITIONAL_STREAMS_MAX, res = SzReadAndDecodePackedStreams(inStream, sd, tempBufs, NUM_ADDITIONAL_STREAMS_MAX,
p->startPosAfterHeader, &tempAr, allocTemp); p->startPosAfterHeader, &tempAr, allocTemp);
numTempFolders = tempAr.NumFolders; *numTempBufs = tempAr.NumFolders;
SzAr_Free(&tempAr, allocTemp); SzAr_Free(&tempAr, allocTemp);
if (res != SZ_OK) if (res != SZ_OK)
return res; return res;
*numTempBufs = numTempFolders;
RINOK(ReadID(sd, &type)); RINOK(ReadID(sd, &type));
} }
@@ -1270,9 +1159,9 @@ static SRes SzReadHeader2(
if (type == k7zIdEnd) if (type == k7zIdEnd)
{ {
// *sd2 = sd;
return SZ_OK; return SZ_OK;
} }
if (type != k7zIdFilesInfo) if (type != k7zIdFilesInfo)
return SZ_ERROR_ARCHIVE; return SZ_ERROR_ARCHIVE;
@@ -1333,6 +1222,7 @@ static SRes SzReadHeader2(
{ {
RINOK(RememberBitVector(sd, numFiles, &emptyStreams)); RINOK(RememberBitVector(sd, numFiles, &emptyStreams));
numEmptyStreams = CountDefinedBits(emptyStreams, numFiles); numEmptyStreams = CountDefinedBits(emptyStreams, numFiles);
emptyFiles = NULL;
break; break;
} }
case k7zIdEmptyFile: case k7zIdEmptyFile:
@@ -1402,21 +1292,17 @@ static SRes SzReadHeader2(
UInt32 remSubStreams = 0; UInt32 remSubStreams = 0;
UInt32 numSubStreams = 0; UInt32 numSubStreams = 0;
UInt64 unpackPos = 0; UInt64 unpackPos = 0;
const Byte *digestsDefs = 0; const Byte *digestsDefs = NULL;
const Byte *digestsVals = 0; const Byte *digestsVals = NULL;
UInt32 digestsValsIndex = 0; UInt32 digestsValsIndex = 0;
UInt32 digestIndex; UInt32 digestIndex;
Byte allDigestsDefined = 0; Byte allDigestsDefined = 0;
Byte isDirMask = 0; Byte isDirMask = 0;
Byte crcMask = 0; Byte crcMask = 0;
Byte mask = 0x80; Byte mask = 0x80;
CSzData sdCodersUnpSizes;
sdCodersUnpSizes.Data = p->db.UnpackSizesData;
sdCodersUnpSizes.Size = p->db.UnpackSizesDataSize;
MY_ALLOC(UInt32, p->FolderStartFileIndex, p->db.NumFolders + 1, allocMain); MY_ALLOC(UInt32, p->FolderToFile, p->db.NumFolders + 1, allocMain);
MY_ALLOC_ZE(UInt32, p->FileIndexToFolderIndexMap, p->NumFiles, allocMain); MY_ALLOC_ZE(UInt32, p->FileToFolder, p->NumFiles, allocMain);
MY_ALLOC(UInt64, p->UnpackPositions, p->NumFiles + 1, allocMain); MY_ALLOC(UInt64, p->UnpackPositions, p->NumFiles + 1, allocMain);
MY_ALLOC_ZE(Byte, p->IsDirs, (p->NumFiles + 7) >> 3, allocMain); MY_ALLOC_ZE(Byte, p->IsDirs, (p->NumFiles + 7) >> 3, allocMain);
@@ -1424,7 +1310,7 @@ static SRes SzReadHeader2(
if (ssi.sdCRCs.Size != 0) if (ssi.sdCRCs.Size != 0)
{ {
RINOK(SzReadByte(&ssi.sdCRCs, &allDigestsDefined)); SZ_READ_BYTE_SD(&ssi.sdCRCs, allDigestsDefined);
if (allDigestsDefined) if (allDigestsDefined)
digestsVals = ssi.sdCRCs.Data; digestsVals = ssi.sdCRCs.Data;
else else
@@ -1454,12 +1340,17 @@ static SRes SzReadHeader2(
if (emptyStreams && SzBitArray_Check(emptyStreams, i)) if (emptyStreams && SzBitArray_Check(emptyStreams, i))
{ {
if (!emptyFiles || !SzBitArray_Check(emptyFiles, emptyFileIndex)) if (emptyFiles)
{
if (!SzBitArray_Check(emptyFiles, emptyFileIndex))
isDirMask |= mask;
emptyFileIndex++;
}
else
isDirMask |= mask; isDirMask |= mask;
emptyFileIndex++;
if (remSubStreams == 0) if (remSubStreams == 0)
{ {
p->FileIndexToFolderIndexMap[i] = (UInt32)-1; p->FileToFolder[i] = (UInt32)-1;
continue; continue;
} }
} }
@@ -1470,7 +1361,7 @@ static SRes SzReadHeader2(
{ {
if (folderIndex >= p->db.NumFolders) if (folderIndex >= p->db.NumFolders)
return SZ_ERROR_ARCHIVE; return SZ_ERROR_ARCHIVE;
p->FolderStartFileIndex[folderIndex] = i; p->FolderToFile[folderIndex] = i;
numSubStreams = 1; numSubStreams = 1;
if (ssi.sdNumSubStreams.Data) if (ssi.sdNumSubStreams.Data)
{ {
@@ -1479,45 +1370,31 @@ static SRes SzReadHeader2(
remSubStreams = numSubStreams; remSubStreams = numSubStreams;
if (numSubStreams != 0) if (numSubStreams != 0)
break; break;
p->db.FoSizesOffsets[folderIndex] = sdCodersUnpSizes.Data - p->db.UnpackSizesData; {
UInt64 folderUnpackSize = SzAr_GetFolderUnpackSize(&p->db, folderIndex);
unpackPos += folderUnpackSize;
if (unpackPos < folderUnpackSize)
return SZ_ERROR_ARCHIVE;
}
folderIndex++; folderIndex++;
} }
} }
p->FileIndexToFolderIndexMap[i] = folderIndex; p->FileToFolder[i] = folderIndex;
if (emptyStreams && SzBitArray_Check(emptyStreams, i)) if (emptyStreams && SzBitArray_Check(emptyStreams, i))
continue; continue;
if (--remSubStreams == 0) if (--remSubStreams == 0)
{ {
UInt64 folderUnpackSize = 0; UInt64 folderUnpackSize = SzAr_GetFolderUnpackSize(&p->db, folderIndex);
UInt64 startFolderUnpackPos; UInt64 startFolderUnpackPos = p->UnpackPositions[p->FolderToFile[folderIndex]];
{
UInt32 mix = (UInt32)p->db.FoSizesOffsets[folderIndex];
UInt32 mainIndex = mix & 0xFF;
UInt32 numOutStreams = mix >> 8;
UInt32 si;
p->db.FoSizesOffsets[folderIndex] = sdCodersUnpSizes.Data - p->db.UnpackSizesData;
for (si = 0; si < numOutStreams; si++)
{
UInt64 curSize;
RINOK(ReadNumber(&sdCodersUnpSizes, &curSize));
if (si == mainIndex)
{
folderUnpackSize = curSize;
break;
}
}
if (si == numOutStreams)
return SZ_ERROR_FAIL;
}
// UInt64 folderUnpackSize = SzAr_GetFolderUnpackSize(&p->db, folderIndex);
startFolderUnpackPos = p->UnpackPositions[p->FolderStartFileIndex[folderIndex]];
if (folderUnpackSize < unpackPos - startFolderUnpackPos) if (folderUnpackSize < unpackPos - startFolderUnpackPos)
return SZ_ERROR_ARCHIVE; return SZ_ERROR_ARCHIVE;
unpackPos = startFolderUnpackPos + folderUnpackSize; unpackPos = startFolderUnpackPos + folderUnpackSize;
if (unpackPos < folderUnpackSize)
return SZ_ERROR_ARCHIVE;
if (numSubStreams == 1 && SzBitWithVals_Check(&p->db.FolderCRCs, i)) if (numSubStreams == 1 && SzBitWithVals_Check(&p->db.FolderCRCs, i))
{ {
@@ -1557,12 +1434,39 @@ static SRes SzReadHeader2(
} }
p->UnpackPositions[i] = unpackPos; p->UnpackPositions[i] = unpackPos;
p->FolderStartFileIndex[folderIndex] = i;
p->db.FoSizesOffsets[folderIndex] = sdCodersUnpSizes.Data - p->db.UnpackSizesData; 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; return SZ_OK;
} }
static SRes SzReadHeader( static SRes SzReadHeader(
CSzArEx *p, CSzArEx *p,
CSzData *sd, CSzData *sd,
@@ -1570,9 +1474,6 @@ static SRes SzReadHeader(
ISzAlloc *allocMain, ISzAlloc *allocMain,
ISzAlloc *allocTemp) ISzAlloc *allocTemp)
{ {
// Byte *emptyStreamVector = 0;
// Byte *emptyFileVector = 0;
// Byte *lwtVector = 0;
UInt32 i; UInt32 i;
UInt32 numTempBufs = 0; UInt32 numTempBufs = 0;
SRes res; SRes res;
@@ -1580,55 +1481,22 @@ static SRes SzReadHeader(
for (i = 0; i < NUM_ADDITIONAL_STREAMS_MAX; i++) for (i = 0; i < NUM_ADDITIONAL_STREAMS_MAX; i++)
Buf_Init(tempBufs + i); Buf_Init(tempBufs + i);
// SzBitUi32s_Init(&digests);
res = SzReadHeader2(p, sd, res = SzReadHeader2(p, sd, inStream,
// &emptyStreamVector,
// &emptyFileVector,
// &lwtVector,
inStream,
tempBufs, &numTempBufs, tempBufs, &numTempBufs,
allocMain, allocTemp allocMain, allocTemp);
);
for (i = 0; i < numTempBufs; i++) for (i = 0; i < NUM_ADDITIONAL_STREAMS_MAX; i++)
Buf_Free(tempBufs + i, allocTemp); Buf_Free(tempBufs + i, allocTemp);
// IAlloc_Free(allocTemp, emptyStreamVector);
// IAlloc_Free(allocTemp, emptyFileVector);
// IAlloc_Free(allocTemp, lwtVector);
RINOK(res); RINOK(res);
{
if (sd->Size != 0) if (sd->Size != 0)
return SZ_ERROR_FAIL; return SZ_ERROR_FAIL;
}
return res; return res;
} }
/*
static UInt64 SzAr_GetFolderUnpackSize(const CSzAr *p, UInt32 folderIndex)
{
const CSzFolder2 *f = p->Folders + folderIndex;
// return p->CoderUnpackSizes[f->StartCoderUnpackSizesIndex + f->IndexOfMainOutStream];
UInt32 si;
CSzData sdCodersUnpSizes;
sdCodersUnpSizes.Data = p->UnpackSizesData + f->UnpackSizeDataOffset;
sdCodersUnpSizes.Size = p->UnpackSizesDataSize - f->UnpackSizeDataOffset;
for (si = 0; si < numOutStreams; si++)
{
UInt64 curSize;
ReadNumber(&sdCodersUnpSizes, &curSize);
if (si == mainIndex)
return curSize;
}
return 0;
}
*/
static SRes SzArEx_Open2( static SRes SzArEx_Open2(
CSzArEx *p, CSzArEx *p,
ILookInStream *inStream, ILookInStream *inStream,
@@ -1686,6 +1554,7 @@ static SRes SzArEx_Open2(
return SZ_ERROR_MEM; return SZ_ERROR_MEM;
res = LookInStream_Read(inStream, buf.data, nextHeaderSizeT); res = LookInStream_Read(inStream, buf.data, nextHeaderSizeT);
if (res == SZ_OK) if (res == SZ_OK)
{ {
res = SZ_ERROR_ARCHIVE; res = SZ_ERROR_ARCHIVE;
@@ -1695,7 +1564,9 @@ static SRes SzArEx_Open2(
UInt64 type; UInt64 type;
sd.Data = buf.data; sd.Data = buf.data;
sd.Size = buf.size; sd.Size = buf.size;
res = ReadID(&sd, &type); res = ReadID(&sd, &type);
if (res == SZ_OK && type == k7zIdEncodedHeader) if (res == SZ_OK && type == k7zIdEncodedHeader)
{ {
CSzAr tempAr; CSzAr tempAr;
@@ -1720,6 +1591,7 @@ static SRes SzArEx_Open2(
res = ReadID(&sd, &type); res = ReadID(&sd, &type);
} }
} }
if (res == SZ_OK) if (res == SZ_OK)
{ {
if (type == k7zIdHeader) if (type == k7zIdHeader)
@@ -1743,11 +1615,11 @@ static SRes SzArEx_Open2(
} }
} }
} }
Buf_Free(&buf, allocTemp); Buf_Free(&buf, allocTemp);
return res; return res;
} }
// #include <stdio.h>
SRes SzArEx_Open(CSzArEx *p, ILookInStream *inStream, SRes SzArEx_Open(CSzArEx *p, ILookInStream *inStream,
ISzAlloc *allocMain, ISzAlloc *allocTemp) ISzAlloc *allocMain, ISzAlloc *allocTemp)
@@ -1755,10 +1627,10 @@ SRes SzArEx_Open(CSzArEx *p, ILookInStream *inStream,
SRes res = SzArEx_Open2(p, inStream, allocMain, allocTemp); SRes res = SzArEx_Open2(p, inStream, allocMain, allocTemp);
if (res != SZ_OK) if (res != SZ_OK)
SzArEx_Free(p, allocMain); SzArEx_Free(p, allocMain);
// printf ("\nrrr=%d\n", rrr);
return res; return res;
} }
SRes SzArEx_Extract( SRes SzArEx_Extract(
const CSzArEx *p, const CSzArEx *p,
ILookInStream *inStream, ILookInStream *inStream,
@@ -1771,34 +1643,36 @@ SRes SzArEx_Extract(
ISzAlloc *allocMain, ISzAlloc *allocMain,
ISzAlloc *allocTemp) ISzAlloc *allocTemp)
{ {
UInt32 folderIndex = p->FileIndexToFolderIndexMap[fileIndex]; UInt32 folderIndex = p->FileToFolder[fileIndex];
SRes res = SZ_OK; SRes res = SZ_OK;
*offset = 0; *offset = 0;
*outSizeProcessed = 0; *outSizeProcessed = 0;
if (folderIndex == (UInt32)-1) if (folderIndex == (UInt32)-1)
{ {
IAlloc_Free(allocMain, *tempBuf); IAlloc_Free(allocMain, *tempBuf);
*blockIndex = folderIndex; *blockIndex = folderIndex;
*tempBuf = 0; *tempBuf = NULL;
*outBufferSize = 0; *outBufferSize = 0;
return SZ_OK; return SZ_OK;
} }
if (*tempBuf == 0 || *blockIndex != folderIndex) if (*tempBuf == NULL || *blockIndex != folderIndex)
{ {
// UInt64 unpackSizeSpec = SzAr_GetFolderUnpackSize(&p->db, folderIndex); UInt64 unpackSizeSpec = SzAr_GetFolderUnpackSize(&p->db, folderIndex);
/*
UInt64 unpackSizeSpec = UInt64 unpackSizeSpec =
p->UnpackPositions[p->FolderStartFileIndex[folderIndex + 1]] - p->UnpackPositions[p->FolderToFile[folderIndex + 1]] -
p->UnpackPositions[p->FolderStartFileIndex[folderIndex]]; p->UnpackPositions[p->FolderToFile[folderIndex]];
*/
size_t unpackSize = (size_t)unpackSizeSpec; size_t unpackSize = (size_t)unpackSizeSpec;
if (unpackSize != unpackSizeSpec) if (unpackSize != unpackSizeSpec)
return SZ_ERROR_MEM; return SZ_ERROR_MEM;
*blockIndex = folderIndex; *blockIndex = folderIndex;
IAlloc_Free(allocMain, *tempBuf); IAlloc_Free(allocMain, *tempBuf);
*tempBuf = 0; *tempBuf = NULL;
// RINOK(LookInStream_SeekTo(inStream, startOffset));
if (res == SZ_OK) if (res == SZ_OK)
{ {
@@ -1806,36 +1680,30 @@ SRes SzArEx_Extract(
if (unpackSize != 0) if (unpackSize != 0)
{ {
*tempBuf = (Byte *)IAlloc_Alloc(allocMain, unpackSize); *tempBuf = (Byte *)IAlloc_Alloc(allocMain, unpackSize);
if (*tempBuf == 0) if (*tempBuf == NULL)
res = SZ_ERROR_MEM; res = SZ_ERROR_MEM;
} }
if (res == SZ_OK) if (res == SZ_OK)
{ {
res = SzAr_DecodeFolder(&p->db, folderIndex, res = SzAr_DecodeFolder(&p->db, folderIndex,
inStream, inStream, p->dataPos, *tempBuf, unpackSize, allocTemp);
p->dataPos,
*tempBuf, unpackSize, allocTemp);
if (res == SZ_OK)
{
if (SzBitWithVals_Check(&p->db.FolderCRCs, folderIndex))
{
if (CrcCalc(*tempBuf, unpackSize) != p->db.FolderCRCs.Vals[folderIndex])
res = SZ_ERROR_CRC;
}
}
} }
} }
} }
if (res == SZ_OK) if (res == SZ_OK)
{ {
UInt64 unpackPos = p->UnpackPositions[fileIndex]; UInt64 unpackPos = p->UnpackPositions[fileIndex];
*offset = (size_t)(unpackPos - p->UnpackPositions[p->FolderStartFileIndex[folderIndex]]); *offset = (size_t)(unpackPos - p->UnpackPositions[p->FolderToFile[folderIndex]]);
*outSizeProcessed = (size_t)(p->UnpackPositions[fileIndex + 1] - unpackPos); *outSizeProcessed = (size_t)(p->UnpackPositions[fileIndex + 1] - unpackPos);
if (*offset + *outSizeProcessed > *outBufferSize) if (*offset + *outSizeProcessed > *outBufferSize)
return SZ_ERROR_FAIL; return SZ_ERROR_FAIL;
if (SzBitWithVals_Check(&p->CRCs, fileIndex) && CrcCalc(*tempBuf + *offset, *outSizeProcessed) != p->CRCs.Vals[fileIndex]) if (SzBitWithVals_Check(&p->CRCs, fileIndex))
res = SZ_ERROR_CRC; if (CrcCalc(*tempBuf + *offset, *outSizeProcessed) != p->CRCs.Vals[fileIndex])
res = SZ_ERROR_CRC;
} }
return res; return res;
} }

View File

@@ -1,5 +1,5 @@
/* 7zDec.c -- Decoding from 7z folder /* 7zDec.c -- Decoding from 7z folder
2015-08-01 : Igor Pavlov : Public domain */ 2015-11-18 : Igor Pavlov : Public domain */
#include "Precomp.h" #include "Precomp.h"
@@ -8,6 +8,7 @@
/* #define _7ZIP_PPMD_SUPPPORT */ /* #define _7ZIP_PPMD_SUPPPORT */
#include "7z.h" #include "7z.h"
#include "7zCrc.h"
#include "Bcj2.h" #include "Bcj2.h"
#include "Bra.h" #include "Bra.h"
@@ -160,14 +161,23 @@ static SRes SzDecodeLzma(const Byte *props, unsigned propsSize, UInt64 inSize, I
inSize -= inProcessed; inSize -= inProcessed;
if (res != SZ_OK) if (res != SZ_OK)
break; break;
if (state.dicPos == state.dicBufSize || (inProcessed == 0 && dicPos == state.dicPos))
if (status == LZMA_STATUS_FINISHED_WITH_MARK)
{ {
if (state.dicBufSize != outSize || lookahead != 0 || if (outSize != state.dicPos || inSize != 0)
(status != LZMA_STATUS_FINISHED_WITH_MARK &&
status != LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK))
res = SZ_ERROR_DATA; res = SZ_ERROR_DATA;
break; break;
} }
if (outSize == state.dicPos && inSize == 0 && status == LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK)
break;
if (inProcessed == 0 && dicPos == state.dicPos)
{
res = SZ_ERROR_DATA;
break;
}
res = inStream->Skip((void *)inStream, inProcessed); res = inStream->Skip((void *)inStream, inProcessed);
if (res != SZ_OK) if (res != SZ_OK)
break; break;
@@ -213,13 +223,20 @@ static SRes SzDecodeLzma2(const Byte *props, unsigned propsSize, UInt64 inSize,
inSize -= inProcessed; inSize -= inProcessed;
if (res != SZ_OK) if (res != SZ_OK)
break; break;
if (state.decoder.dicPos == state.decoder.dicBufSize || (inProcessed == 0 && dicPos == state.decoder.dicPos))
if (status == LZMA_STATUS_FINISHED_WITH_MARK)
{ {
if (state.decoder.dicBufSize != outSize || lookahead != 0 || if (outSize != state.decoder.dicPos || inSize != 0)
(status != LZMA_STATUS_FINISHED_WITH_MARK))
res = SZ_ERROR_DATA; res = SZ_ERROR_DATA;
break; break;
} }
if (inProcessed == 0 && dicPos == state.decoder.dicPos)
{
res = SZ_ERROR_DATA;
break;
}
res = inStream->Skip((void *)inStream, inProcessed); res = inStream->Skip((void *)inStream, inProcessed);
if (res != SZ_OK) if (res != SZ_OK)
break; break;
@@ -537,33 +554,38 @@ SRes SzAr_DecodeFolder(const CSzAr *p, UInt32 folderIndex,
SRes res; SRes res;
CSzFolder folder; CSzFolder folder;
CSzData sd; CSzData sd;
CSzData sdSizes;
const Byte *data = p->CodersData + p->FoCodersOffsets[folderIndex]; const Byte *data = p->CodersData + p->FoCodersOffsets[folderIndex];
sd.Data = data; sd.Data = data;
sd.Size = p->FoCodersOffsets[folderIndex + 1] - p->FoCodersOffsets[folderIndex]; sd.Size = p->FoCodersOffsets[folderIndex + 1] - p->FoCodersOffsets[folderIndex];
sdSizes.Data = p->UnpackSizesData + p->FoSizesOffsets[folderIndex]; res = SzGetNextFolderItem(&folder, &sd);
sdSizes.Size =
p->FoSizesOffsets[folderIndex + 1] -
p->FoSizesOffsets[folderIndex];
res = SzGetNextFolderItem(&folder, &sd, &sdSizes);
if (res != SZ_OK) if (res != SZ_OK)
return res; return res;
if (sd.Size != 0 || outSize != folder.CodersUnpackSizes[folder.UnpackStream]) if (sd.Size != 0
|| folder.UnpackStream != p->FoToMainUnpackSizeIndex[folderIndex]
|| outSize != SzAr_GetFolderUnpackSize(p, folderIndex))
return SZ_ERROR_FAIL; return SZ_ERROR_FAIL;
{ {
unsigned i; unsigned i;
Byte *tempBuf[3] = { 0, 0, 0}; Byte *tempBuf[3] = { 0, 0, 0};
res = SzFolder_Decode2(&folder, data, folder.CodersUnpackSizes,
res = SzFolder_Decode2(&folder, data,
&p->CoderUnpackSizes[p->FoToCoderUnpackSizes[folderIndex]],
p->PackPositions + p->FoStartPackStreamIndex[folderIndex], p->PackPositions + p->FoStartPackStreamIndex[folderIndex],
inStream, startPos, inStream, startPos,
outBuffer, (SizeT)outSize, allocMain, tempBuf); outBuffer, (SizeT)outSize, allocMain, tempBuf);
for (i = 0; i < 3; i++) for (i = 0; i < 3; i++)
IAlloc_Free(allocMain, tempBuf[i]); IAlloc_Free(allocMain, tempBuf[i]);
if (res == SZ_OK)
if (SzBitWithVals_Check(&p->FolderCRCs, folderIndex))
if (CrcCalc(outBuffer, outSize) != p->FolderCRCs.Vals[folderIndex])
res = SZ_ERROR_CRC;
return res; return res;
} }
} }

View File

@@ -1,9 +1,9 @@
#define MY_VER_MAJOR 15 #define MY_VER_MAJOR 15
#define MY_VER_MINOR 11 #define MY_VER_MINOR 12
#define MY_VER_BUILD 0 #define MY_VER_BUILD 0
#define MY_VERSION_NUMBERS "15.11" #define MY_VERSION_NUMBERS "15.12"
#define MY_VERSION "15.11 beta" #define MY_VERSION "15.12"
#define MY_DATE "2015-11-14" #define MY_DATE "2015-11-19"
#undef MY_COPYRIGHT #undef MY_COPYRIGHT
#undef MY_VERSION_COPYRIGHT_DATE #undef MY_VERSION_COPYRIGHT_DATE
#define MY_AUTHOR_NAME "Igor Pavlov" #define MY_AUTHOR_NAME "Igor Pavlov"

View File

@@ -73,4 +73,3 @@ Ppmd7Dec.o: ../../Ppmd7Dec.c
clean: clean:
-$(RM) $(PROG) $(OBJS) -$(RM) $(PROG) $(OBJS)

View File

@@ -373,6 +373,8 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
ConvertUInt32ToString(f.AlgId, temp + 1); ConvertUInt32ToString(f.AlgId, temp + 1);
m += temp; m += temp;
} }
if (f.CertificateIsUsed())
m += "-Cert";
} }
else else
m += kMethod_StrongCrypto; m += kMethod_StrongCrypto;

View File

@@ -109,6 +109,8 @@ struct CStrongCryptoExtra
Flags = GetUi16(p + 6); Flags = GetUi16(p + 6);
return (Format == 2); return (Format == 2);
} }
bool CertificateIsUsed() const { return (Flags > 0x0001); }
}; };
struct CExtraBlock struct CExtraBlock

View File

@@ -107,4 +107,4 @@ C_OBJS = \
!include "../../Aes.mak" !include "../../Aes.mak"
!include "../../Crc.mak" !include "../../Crc.mak"
!include "../../7zip.mak" !include "../../7zip.mak"

View File

@@ -112,25 +112,87 @@ HRESULT CDecoder::Init_and_CheckPassword(bool &passwOK)
if (algId * 64 + 128 != bitLen) if (algId * 64 + 128 != bitLen)
return E_NOTIMPL; return E_NOTIMPL;
_key.KeySize = 16 + algId * 8; _key.KeySize = 16 + algId * 8;
if ((flags & 1) == 0) bool cert = ((flags & 2) != 0);
return E_NOTIMPL;
if ((flags & 0x4000) != 0) if ((flags & 0x4000) != 0)
{ {
// Use 3DES // Use 3DES
return E_NOTIMPL; return E_NOTIMPL;
} }
if (cert)
{
return E_NOTIMPL;
}
else
{
if ((flags & 1) == 0)
return E_NOTIMPL;
}
UInt32 rdSize = GetUi16(p + 8); UInt32 rdSize = GetUi16(p + 8);
if ((rdSize & 0xF) != 0 || rdSize + 16 > _remSize)
return E_NOTIMPL; if (rdSize + 16 > _remSize)
memmove(p, p + 10, rdSize);
Byte *validData = p + rdSize + 16;
if (GetUi32(validData - 6) != 0) // reserved
return E_NOTIMPL;
UInt32 validSize = GetUi16(validData - 2);
if ((validSize & 0xF) != 0 || 16 + rdSize + validSize != _remSize)
return E_NOTIMPL; return E_NOTIMPL;
/*
if (cert)
{
// how to filter rd, if ((rdSize & 0xF) != 0) ?
/*
if ((rdSize & 0x7) != 0)
return E_NOTIMPL;
}
else
*/
{
if ((rdSize & 0xF) != 0)
return E_NOTIMPL;
}
memmove(p, p + 10, rdSize);
const Byte *p2 = p + rdSize + 10;
UInt32 reserved = GetUi32(p2);
p2 += 4;
/*
if (cert)
{
UInt32 numRecipients = reserved;
if (numRecipients == 0)
return E_NOTIMPL;
{
UInt32 hashAlg = GetUi16(p2);
hashAlg = hashAlg;
UInt32 hashSize = GetUi16(p2 + 2);
hashSize = hashSize;
p2 += 4;
reserved = reserved;
// return E_NOTIMPL;
for (unsigned r = 0; r < numRecipients; r++)
{
UInt32 specSize = GetUi16(p2);
p2 += 2;
p2 += specSize;
}
}
}
else
*/
{
if (reserved != 0)
return E_NOTIMPL;
}
UInt32 validSize = GetUi16(p2);
p2 += 2;
const size_t validOffset = p2 - p;
if ((validSize & 0xF) != 0 || validOffset + validSize != _remSize)
return E_NOTIMPL;
{ {
RINOK(SetKey(_key.MasterKey, _key.KeySize)); RINOK(SetKey(_key.MasterKey, _key.KeySize));
@@ -149,12 +211,14 @@ HRESULT CDecoder::Init_and_CheckPassword(bool &passwOK)
RINOK(SetKey(fileKey, _key.KeySize)); RINOK(SetKey(fileKey, _key.KeySize));
RINOK(SetInitVector(_iv, 16)); RINOK(SetInitVector(_iv, 16));
Init(); Init();
Filter(validData, validSize);
memmove(p, p + validOffset, validSize);
Filter(p, validSize);
if (validSize < 4) if (validSize < 4)
return E_NOTIMPL; return E_NOTIMPL;
validSize -= 4; validSize -= 4;
if (GetUi32(validData + validSize) != CrcCalc(validData, validSize)) if (GetUi32(p + validSize) != CrcCalc(p, validSize))
return S_OK; return S_OK;
passwOK = true; passwOK = true;
return S_OK; return S_OK;

View File

@@ -33,3 +33,4 @@ UI_COMMON_OBJS = \
$O\UpdatePair.obj \ $O\UpdatePair.obj \
$O\UpdateProduce.obj \ $O\UpdateProduce.obj \
#

View File

@@ -1097,6 +1097,7 @@ void CPanel::SaveListViewInfo()
viewInfo.SortID = sortPropID; viewInfo.SortID = sortPropID;
viewInfo.Ascending = _ascending; viewInfo.Ascending = _ascending;
viewInfo.IsLoaded = true;
if (!_listViewInfo.IsEqual(viewInfo)) if (!_listViewInfo.IsEqual(viewInfo))
{ {
viewInfo.Save(_typeIDString); viewInfo.Save(_typeIDString);

View File

@@ -175,6 +175,7 @@ void AddHashBundleRes(UString &s, const CHashBundle &hb, const UString &firstFil
AddValuePair(s, IDS_PROP_NUM_ERRORS, hb.NumErrors); AddValuePair(s, IDS_PROP_NUM_ERRORS, hb.NumErrors);
s.Add_LF(); s.Add_LF();
} }
if (hb.NumFiles == 1 && hb.NumDirs == 0 && !firstFileName.IsEmpty()) if (hb.NumFiles == 1 && hb.NumDirs == 0 && !firstFileName.IsEmpty())
{ {
AddLangString(s, IDS_PROP_NAME); AddLangString(s, IDS_PROP_NAME);
@@ -197,6 +198,12 @@ void AddHashBundleRes(UString &s, const CHashBundle &hb, const UString &firstFil
AddSizeValuePair(s, IDS_PROP_ALT_STREAMS_SIZE, hb.AltStreamsSize); AddSizeValuePair(s, IDS_PROP_ALT_STREAMS_SIZE, hb.AltStreamsSize);
} }
if (hb.NumErrors == 0 && hb.Hashers.IsEmpty())
{
s.Add_LF();
AddLangString(s, IDS_MESSAGE_NO_ERRORS);
}
FOR_VECTOR (i, hb.Hashers) FOR_VECTOR (i, hb.Hashers)
{ {
s.Add_LF(); s.Add_LF();

View File

@@ -10,8 +10,8 @@ AppName = "7-Zip"
InstallDir = %CE1%\%AppName% InstallDir = %CE1%\%AppName%
[Strings] [Strings]
AppVer = "15.11" AppVer = "15.12"
AppDate = "2015-11-14" AppDate = "2015-11-19"
[CEDevice] [CEDevice]
; ProcessorType = 2577 ; ARM ; ProcessorType = 2577 ; ARM

View File

@@ -2,8 +2,8 @@
;Defines ;Defines
!define VERSION_MAJOR 15 !define VERSION_MAJOR 15
!define VERSION_MINOR 11 !define VERSION_MINOR 12
!define VERSION_POSTFIX_FULL " beta" !define VERSION_POSTFIX_FULL ""
!ifdef WIN64 !ifdef WIN64
!ifdef IA64 !ifdef IA64
!define VERSION_SYS_POSTFIX_FULL " for Windows IA-64" !define VERSION_SYS_POSTFIX_FULL " for Windows IA-64"

View File

@@ -1,7 +1,7 @@
<?xml version="1.0"?> <?xml version="1.0"?>
<?define VerMajor = "15" ?> <?define VerMajor = "15" ?>
<?define VerMinor = "11" ?> <?define VerMinor = "12" ?>
<?define VerBuild = "00" ?> <?define VerBuild = "00" ?>
<?define MmVer = "$(var.VerMajor).$(var.VerMinor)" ?> <?define MmVer = "$(var.VerMajor).$(var.VerMinor)" ?>
<?define MmHex = "$(var.VerMajor)$(var.VerMinor)" ?> <?define MmHex = "$(var.VerMajor)$(var.VerMinor)" ?>

View File

@@ -1,4 +1,4 @@
7-Zip 15.11 Sources 7-Zip 15.12 Sources
------------------- -------------------
7-Zip is a file archiver for Windows. 7-Zip is a file archiver for Windows.

View File

@@ -1,6 +1,21 @@
HISTORY of the 7-Zip source code HISTORY of the 7-Zip source code
-------------------------------- --------------------------------
15.12 2015-11-19
-------------------------
- The BUG in C version of 7z decoder was fixed:
7zDec.c : SzDecodeLzma2()
7z decoder could mistakenly report about decoding error for some 7z archives
that use LZMA2 compression method.
The probability to get that mistaken decoding error report was about
one error per 16384 solid blocks for solid blocks larger than 16 KB (compressed size).
- The BUG (in 9.26-15.11) in C version of 7z decoder was fixed:
7zArcIn.c : SzReadHeader2()
7z decoder worked incorrectly for 7z archives that contain
empty solid blocks, that can be placed to 7z archive, if some file is
unavailable for reading during archive creation.
15.09 beta 2015-10-16 15.09 beta 2015-10-16
------------------------- -------------------------
- The BUG in LZMA / LZMA2 encoding code was fixed. - The BUG in LZMA / LZMA2 encoding code was fixed.