PeHandler.cpp (p7zip_15.14.1_src_all) | : | PeHandler.cpp (p7zip_16.02_src_all) | ||
---|---|---|---|---|
skipping to change at line 245 | skipping to change at line 245 | |||
UInt64 HeapCommit; | UInt64 HeapCommit; | |||
UInt32 NumDirItems; | UInt32 NumDirItems; | |||
CDirLink DirItems[kNumDirItemsMax]; | CDirLink DirItems[kNumDirItemsMax]; | |||
bool Is64Bit() const { return Magic == PE_OptHeader_Magic_64; } | bool Is64Bit() const { return Magic == PE_OptHeader_Magic_64; } | |||
bool Parse(const Byte *p, UInt32 size); | bool Parse(const Byte *p, UInt32 size); | |||
int GetNumFileAlignBits() const | int GetNumFileAlignBits() const | |||
{ | { | |||
for (int i = 9; i <= 16; i++) | for (unsigned i = 0; i <= 31; i++) | |||
if (((UInt32)1 << i) == FileAlign) | if (((UInt32)1 << i) == FileAlign) | |||
return i; | return i; | |||
return -1; | return -1; | |||
} | } | |||
bool IsSybSystem_EFI() const | bool IsSybSystem_EFI() const | |||
{ | { | |||
return | return | |||
SubSystem >= k_SubSystems_EFI_First && | SubSystem >= k_SubSystems_EFI_First && | |||
SubSystem <= k_SubSystems_EFI_Last; | SubSystem <= k_SubSystems_EFI_Last; | |||
skipping to change at line 350 | skipping to change at line 350 | |||
UInt32 Pa; | UInt32 Pa; | |||
UInt32 Flags; | UInt32 Flags; | |||
UInt32 Time; | UInt32 Time; | |||
// UInt16 NumRelocs; | // UInt16 NumRelocs; | |||
bool IsRealSect; | bool IsRealSect; | |||
bool IsDebug; | bool IsDebug; | |||
bool IsAdditionalSection; | bool IsAdditionalSection; | |||
CSection(): IsRealSect(false), IsDebug(false), IsAdditionalSection(false) {} | CSection(): IsRealSect(false), IsDebug(false), IsAdditionalSection(false) {} | |||
// const UInt32 GetSize() const { return PSize; } | const UInt32 GetSizeExtract() const { return PSize; } | |||
const UInt32 GetSize() const { return MyMin(PSize, VSize); } | const UInt32 GetSizeMin() const { return MyMin(PSize, VSize); } | |||
void UpdateTotalSize(UInt32 &totalSize) const | void UpdateTotalSize(UInt32 &totalSize) const | |||
{ | { | |||
UInt32 t = Pa + PSize; | UInt32 t = Pa + PSize; | |||
if (totalSize < t) | if (totalSize < t) | |||
totalSize = t; | totalSize = t; | |||
} | } | |||
void Parse(const Byte *p); | void Parse(const Byte *p); | |||
int Compare(const CSection &s) const | int Compare(const CSection &s) const | |||
{ | { | |||
RINOZ(MyCompare(Pa, s.Pa)); | RINOZ(MyCompare(Pa, s.Pa)); | |||
UInt32 size1 = GetSize(); | UInt32 size1 = GetSizeExtract(); | |||
UInt32 size2 = s.GetSize(); | UInt32 size2 = s.GetSizeExtract(); | |||
return MyCompare(size1, size2); | return MyCompare(size1, size2); | |||
} | } | |||
}; | }; | |||
static const unsigned kNameSize = 8; | static const unsigned kNameSize = 8; | |||
static void GetName(const Byte *name, AString &res) | static void GetName(const Byte *name, AString &res) | |||
{ | { | |||
res.SetFrom_CalcLen((const char *)name, kNameSize); | res.SetFrom_CalcLen((const char *)name, kNameSize); | |||
} | } | |||
skipping to change at line 1044 | skipping to change at line 1044 | |||
case kpidSize: prop = (UInt64)item.GetSize(); break; | case kpidSize: prop = (UInt64)item.GetSize(); break; | |||
case kpidPackSize: prop = (UInt64)item.Size; break; | case kpidPackSize: prop = (UInt64)item.Size; break; | |||
} | } | |||
} | } | |||
else | else | |||
{ | { | |||
const CSection &item = _sections[mixItem.SectionIndex]; | const CSection &item = _sections[mixItem.SectionIndex]; | |||
switch (propID) | switch (propID) | |||
{ | { | |||
case kpidPath: prop = MultiByteToUnicodeString(item.Name); break; | case kpidPath: prop = MultiByteToUnicodeString(item.Name); break; | |||
case kpidSize: prop = (UInt64)item.GetSize(); break; | case kpidSize: prop = (UInt64)item.PSize; break; | |||
case kpidPackSize: prop = (UInt64)item.PSize; break; | case kpidPackSize: prop = (UInt64)item.PSize; break; | |||
case kpidVirtualSize: prop = (UInt64)item.VSize; break; | case kpidVirtualSize: prop = (UInt64)item.VSize; break; | |||
case kpidOffset: prop = item.Pa; break; | case kpidOffset: prop = item.Pa; break; | |||
case kpidVa: if (item.IsRealSect) prop = item.Va; break; | case kpidVa: if (item.IsRealSect) prop = item.Va; break; | |||
case kpidMTime: | case kpidMTime: | |||
case kpidCTime: | case kpidCTime: | |||
TimeToProp(item.IsDebug ? item.Time : _header.Time, prop); break; | TimeToProp(item.IsDebug ? item.Time : _header.Time, prop); break; | |||
case kpidCharacts: if (item.IsRealSect) FLAGS_TO_PROP(g_SectFlags, item.Fl ags, prop); break; | case kpidCharacts: if (item.IsRealSect) FLAGS_TO_PROP(g_SectFlags, item.Fl ags, prop); break; | |||
case kpidZerosTailIsAllowed: if (!item.IsRealSect) prop = true; break; | case kpidZerosTailIsAllowed: if (!item.IsRealSect) prop = true; break; | |||
} | } | |||
skipping to change at line 1153 | skipping to change at line 1153 | |||
CTableItem item; | CTableItem item; | |||
item.ID = Get32(buf + 0); | item.ID = Get32(buf + 0); | |||
if ((bool)((item.ID & kFlag) != 0) != (bool)(i < numNameItems)) | if ((bool)((item.ID & kFlag) != 0) != (bool)(i < numNameItems)) | |||
return S_FALSE; | return S_FALSE; | |||
item.Offset = Get32(buf + 4); | item.Offset = Get32(buf + 4); | |||
items.AddInReserved(item); | items.AddInReserved(item); | |||
} | } | |||
return S_OK; | return S_OK; | |||
} | } | |||
static const UInt32 kFileSizeMax = (UInt32)1 << 30; | static const UInt32 kFileSizeMax = (UInt32)1 << 31; | |||
static const unsigned kNumResItemsMax = (unsigned)1 << 23; | static const unsigned kNumResItemsMax = (unsigned)1 << 23; | |||
static const unsigned kNumStringLangsMax = 256; | static const unsigned kNumStringLangsMax = 256; | |||
// BITMAPINFOHEADER | // BITMAPINFOHEADER | |||
struct CBitmapInfoHeader | struct CBitmapInfoHeader | |||
{ | { | |||
// UInt32 HeaderSize; | // UInt32 HeaderSize; | |||
UInt32 XSize; | UInt32 XSize; | |||
Int32 YSize; | Int32 YSize; | |||
UInt16 Planes; | UInt16 Planes; | |||
skipping to change at line 1895 | skipping to change at line 1895 | |||
f.CloseBlock(2); | f.CloseBlock(2); | |||
} | } | |||
f.CloseBlock(0); | f.CloseBlock(0); | |||
return true; | return true; | |||
} | } | |||
HRESULT CHandler::OpenResources(unsigned sectionIndex, IInStream *stream, IArchi veOpenCallback *callback) | HRESULT CHandler::OpenResources(unsigned sectionIndex, IInStream *stream, IArchi veOpenCallback *callback) | |||
{ | { | |||
const CSection § = _sections[sectionIndex]; | const CSection § = _sections[sectionIndex]; | |||
const size_t fileSize = sect.GetSize(); | size_t fileSize = sect.PSize; | |||
if (fileSize > kFileSizeMax) | ||||
return S_FALSE; | ||||
{ | { | |||
UInt64 fileSize64 = fileSize; | size_t fileSizeMin = sect.PSize; | |||
if (callback) | ||||
RINOK(callback->SetTotal(NULL, &fileSize64)); | if (sect.VSize < sect.PSize) | |||
{ | ||||
fileSize = fileSizeMin = sect.VSize; | ||||
const int numBits = _optHeader.GetNumFileAlignBits(); | ||||
if (numBits > 0) | ||||
{ | ||||
const UInt32 mask = ((UInt32)1 << numBits) - 1; | ||||
const size_t end = (size_t)((sect.VSize + mask) & (UInt32)~mask); | ||||
if (end > sect.VSize) | ||||
if (end <= sect.PSize) | ||||
fileSize = end; | ||||
else | ||||
fileSize = sect.PSize; | ||||
} | ||||
} | ||||
if (fileSize > kFileSizeMax) | ||||
return S_FALSE; | ||||
{ | ||||
const UInt64 fileSize64 = fileSize; | ||||
if (callback) | ||||
RINOK(callback->SetTotal(NULL, &fileSize64)); | ||||
} | ||||
RINOK(stream->Seek(sect.Pa, STREAM_SEEK_SET, NULL)); | RINOK(stream->Seek(sect.Pa, STREAM_SEEK_SET, NULL)); | |||
_buf.Alloc(fileSize); | _buf.Alloc(fileSize); | |||
for (size_t pos = 0; pos < fileSize;) | ||||
size_t pos; | ||||
for (pos = 0; pos < fileSize;) | ||||
{ | { | |||
UInt64 offset64 = pos; | { | |||
if (callback) | const UInt64 offset64 = pos; | |||
RINOK(callback->SetCompleted(NULL, &offset64)) | if (callback) | |||
RINOK(callback->SetCompleted(NULL, &offset64)) | ||||
} | ||||
size_t rem = MyMin(fileSize - pos, (size_t)(1 << 22)); | size_t rem = MyMin(fileSize - pos, (size_t)(1 << 22)); | |||
RINOK(ReadStream_FALSE(stream, _buf + pos, rem)); | RINOK(ReadStream(stream, _buf + pos, &rem)); | |||
if (rem == 0) | ||||
{ | ||||
if (pos < fileSizeMin) | ||||
return S_FALSE; | ||||
break; | ||||
} | ||||
pos += rem; | pos += rem; | |||
} | } | |||
if (pos < fileSize) | ||||
memset(_buf + pos, 0, fileSize - pos); | ||||
} | } | |||
_usedRes.Alloc(fileSize); | _usedRes.Alloc(fileSize); | |||
CRecordVector<CTableItem> specItems; | CRecordVector<CTableItem> specItems; | |||
RINOK(ReadTable(0, specItems)); | RINOK(ReadTable(0, specItems)); | |||
_oneLang = true; | _oneLang = true; | |||
bool stringsOk = true; | bool stringsOk = true; | |||
size_t maxOffset = 0; | size_t maxOffset = 0; | |||
FOR_VECTOR (i, specItems) | FOR_VECTOR (i, specItems) | |||
{ | { | |||
const CTableItem &item1 = specItems[i]; | const CTableItem &item1 = specItems[i]; | |||
if ((item1.Offset & kFlag) == 0) | if ((item1.Offset & kFlag) == 0) | |||
return S_FALSE; | return S_FALSE; | |||
CRecordVector<CTableItem> specItems2; | CRecordVector<CTableItem> specItems2; | |||
RINOK(ReadTable(item1.Offset & kMask, specItems2)); | RINOK(ReadTable(item1.Offset & kMask, specItems2)); | |||
FOR_VECTOR (j, specItems2) | FOR_VECTOR (j, specItems2) | |||
skipping to change at line 2004 | skipping to change at line 2041 | |||
mixItem.VersionIndex = _versionFiles.Size(); | mixItem.VersionIndex = _versionFiles.Size(); | |||
mixItem.SectionIndex = sectionIndex; // check it !!!! | mixItem.SectionIndex = sectionIndex; // check it !!!! | |||
CByteBuffer_WithLang &vf = _versionFiles.AddNew(); | CByteBuffer_WithLang &vf = _versionFiles.AddNew(); | |||
vf.Lang = item.Lang; | vf.Lang = item.Lang; | |||
vf.CopyFrom(f.Buf, f.Buf.GetPos()); | vf.CopyFrom(f.Buf, f.Buf.GetPos()); | |||
_mixItems.Add(mixItem); | _mixItems.Add(mixItem); | |||
continue; | continue; | |||
} | } | |||
// PrintError("ver.Parse error"); | // PrintError("ver.Parse error"); | |||
} | } | |||
item.Enabled = true; | item.Enabled = true; | |||
_items.Add(item); | _items.Add(item); | |||
} | } | |||
} | } | |||
} | } | |||
if (stringsOk && !_strings.IsEmpty()) | if (stringsOk && !_strings.IsEmpty()) | |||
{ | { | |||
unsigned i; | unsigned i; | |||
for (i = 0; i < _items.Size(); i++) | for (i = 0; i < _items.Size(); i++) | |||
skipping to change at line 2032 | skipping to change at line 2070 | |||
continue; | continue; | |||
CMixItem mixItem; | CMixItem mixItem; | |||
mixItem.StringIndex = i; | mixItem.StringIndex = i; | |||
mixItem.SectionIndex = sectionIndex; | mixItem.SectionIndex = sectionIndex; | |||
_mixItems.Add(mixItem); | _mixItems.Add(mixItem); | |||
} | } | |||
} | } | |||
_usedRes.Free(); | _usedRes.Free(); | |||
int numBits = _optHeader.GetNumFileAlignBits(); | ||||
if (numBits >= 0) | ||||
{ | { | |||
UInt32 mask = (1 << numBits) - 1; | // PSize can be much larger than VSize in some exe installers. | |||
size_t end = ((maxOffset + mask) & ~mask); | // it contains archive data after PE resources. | |||
// So we need to use PSize here! | ||||
if (/* end < sect.VSize && */ end <= sect.GetSize()) | if (maxOffset < sect.PSize) | |||
{ | { | |||
CSection sect2; | size_t end = fileSize; | |||
sect2.Flags = 0; | ||||
// we skip Zeros to start of aligned block | // we skip Zeros to start of aligned block | |||
size_t i; | size_t i; | |||
for (i = maxOffset; i < end; i++) | for (i = maxOffset; i < end; i++) | |||
if (_buf[i] != 0) | if (_buf[i] != 0) | |||
break; | break; | |||
if (i == end) | if (i == end) | |||
maxOffset = end; | maxOffset = end; | |||
CSection sect2; | ||||
sect2.Flags = 0; | ||||
sect2.Pa = sect.Pa + (UInt32)maxOffset; | sect2.Pa = sect.Pa + (UInt32)maxOffset; | |||
sect2.Va = sect.Va + (UInt32)maxOffset; | sect2.Va = sect.Va + (UInt32)maxOffset; | |||
// 9.29: we use sect.PSize instead of sect.VSize to support some CAB-SFX | // 9.29: we use sect.PSize instead of sect.VSize to support some CAB-SFX | |||
// the code for .rsrc_2 is commented. | // the code for .rsrc_2 is commented. | |||
sect2.PSize = sect.GetSize() - (UInt32)maxOffset; | sect2.PSize = sect.PSize - (UInt32)maxOffset; | |||
if (sect2.PSize != 0) | if (sect2.PSize != 0) | |||
{ | { | |||
sect2.VSize = sect2.PSize; | sect2.VSize = sect2.PSize; | |||
sect2.Name = ".rsrc_1"; | sect2.Name = ".rsrc_1"; | |||
sect2.Time = 0; | sect2.Time = 0; | |||
sect2.IsAdditionalSection = true; | sect2.IsAdditionalSection = true; | |||
_sections.Add(sect2); | _sections.Add(sect2); | |||
} | } | |||
} | } | |||
skipping to change at line 2203 | skipping to change at line 2240 | |||
RINOK(ReadStream(stream, buf, &processed)); | RINOK(ReadStream(stream, buf, &processed)); | |||
/* | /* | |||
if (processed != 0) | if (processed != 0) | |||
{ | { | |||
printf("\ndata after debug %d, %d \n", (int)size, (int)processed); | printf("\ndata after debug %d, %d \n", (int)size, (int)processed); | |||
fflush(stdout); | fflush(stdout); | |||
} | } | |||
*/ | */ | |||
size_t i; | size_t k; | |||
for (i = 0; i < processed; i++) | for (k = 0; k < processed; k++) | |||
if (buf[i] != 0) | if (buf[k] != 0) | |||
break; | break; | |||
if (processed < size && processed < 100) | if (processed < size && processed < 100) | |||
_totalSize += (UInt32)processed; | _totalSize += (UInt32)processed; | |||
else if (((_totalSize + i) & 0x1FF) == 0 || processed < size) | else if (((_totalSize + k) & 0x1FF) == 0 || processed < size) | |||
_totalSize += (UInt32)i; | _totalSize += (UInt32)k; | |||
} | } | |||
} | } | |||
if (_header.NumSymbols > 0 && _header.PointerToSymbolTable >= 512) | if (_header.NumSymbols > 0 && _header.PointerToSymbolTable >= 512) | |||
{ | { | |||
if (_header.NumSymbols >= (1 << 24)) | if (_header.NumSymbols >= (1 << 24)) | |||
return S_FALSE; | return S_FALSE; | |||
UInt32 size = _header.NumSymbols * 18; | UInt32 size = _header.NumSymbols * 18; | |||
RINOK(stream->Seek((UInt64)_header.PointerToSymbolTable + size, STREAM_SEEK_ SET, NULL)); | RINOK(stream->Seek((UInt64)_header.PointerToSymbolTable + size, STREAM_SEEK_ SET, NULL)); | |||
Byte buf[4]; | Byte buf[4]; | |||
skipping to change at line 2240 | skipping to change at line 2277 | |||
sect.Pa = _header.PointerToSymbolTable; | sect.Pa = _header.PointerToSymbolTable; | |||
sect.PSize = sect.VSize = size; | sect.PSize = sect.VSize = size; | |||
sect.UpdateTotalSize(_totalSize); | sect.UpdateTotalSize(_totalSize); | |||
} | } | |||
{ | { | |||
CObjectVector<CSection> sections = _sections; | CObjectVector<CSection> sections = _sections; | |||
sections.Sort(); | sections.Sort(); | |||
UInt32 limit = (1 << 12); | UInt32 limit = (1 << 12); | |||
unsigned num = 0; | unsigned num = 0; | |||
FOR_VECTOR (i, sections) | FOR_VECTOR (k, sections) | |||
{ | { | |||
const CSection &s = sections[i]; | const CSection &s = sections[k]; | |||
if (s.Pa > limit) | if (s.Pa > limit) | |||
{ | { | |||
CSection &s2 = _sections.AddNew(); | CSection &s2 = _sections.AddNew(); | |||
s2.Pa = s2.Va = limit; | s2.Pa = s2.Va = limit; | |||
s2.PSize = s2.VSize = s.Pa - limit; | s2.PSize = s2.VSize = s.Pa - limit; | |||
s2.IsAdditionalSection = true; | s2.IsAdditionalSection = true; | |||
s2.Name = '['; | s2.Name = '['; | |||
s2.Name += GetDecString(num++); | s2.Name += GetDecString(num++); | |||
s2.Name += ']'; | s2.Name += ']'; | |||
limit = s.Pa; | limit = s.Pa; | |||
skipping to change at line 2468 | skipping to change at line 2505 | |||
{ | { | |||
const CMixItem &mixItem = _mixItems[allFilesMode ? i : indices[i]]; | const CMixItem &mixItem = _mixItems[allFilesMode ? i : indices[i]]; | |||
UInt64 size; | UInt64 size; | |||
if (mixItem.StringIndex >= 0) | if (mixItem.StringIndex >= 0) | |||
size = _strings[mixItem.StringIndex].FinalSize(); | size = _strings[mixItem.StringIndex].FinalSize(); | |||
else if (mixItem.VersionIndex >= 0) | else if (mixItem.VersionIndex >= 0) | |||
size = _versionFiles[mixItem.VersionIndex].Size(); | size = _versionFiles[mixItem.VersionIndex].Size(); | |||
else if (mixItem.ResourceIndex >= 0) | else if (mixItem.ResourceIndex >= 0) | |||
size = _items[mixItem.ResourceIndex].GetSize(); | size = _items[mixItem.ResourceIndex].GetSize(); | |||
else | else | |||
size = _sections[mixItem.SectionIndex].GetSize(); | size = _sections[mixItem.SectionIndex].GetSizeExtract(); | |||
totalSize += size; | totalSize += size; | |||
} | } | |||
extractCallback->SetTotal(totalSize); | extractCallback->SetTotal(totalSize); | |||
UInt64 currentTotalSize = 0; | UInt64 currentTotalSize = 0; | |||
UInt64 currentItemSize; | UInt64 currentItemSize; | |||
NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder(); | NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder(); | |||
CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec; | CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec; | |||
skipping to change at line 2544 | skipping to change at line 2581 | |||
isOk = false; | isOk = false; | |||
else if (outStream) | else if (outStream) | |||
{ | { | |||
if (item.HeaderSize != 0) | if (item.HeaderSize != 0) | |||
RINOK(WriteStream(outStream, item.Header, item.HeaderSize)); | RINOK(WriteStream(outStream, item.Header, item.HeaderSize)); | |||
RINOK(WriteStream(outStream, _buf + offset, item.Size)); | RINOK(WriteStream(outStream, _buf + offset, item.Size)); | |||
} | } | |||
} | } | |||
else | else | |||
{ | { | |||
currentItemSize = sect.GetSize(); | currentItemSize = sect.GetSizeExtract(); | |||
if (!testMode && !outStream) | if (!testMode && !outStream) | |||
continue; | continue; | |||
RINOK(extractCallback->PrepareOperation(askMode)); | RINOK(extractCallback->PrepareOperation(askMode)); | |||
RINOK(_stream->Seek(sect.Pa, STREAM_SEEK_SET, NULL)); | RINOK(_stream->Seek(sect.Pa, STREAM_SEEK_SET, NULL)); | |||
streamSpec->Init(currentItemSize); | streamSpec->Init(currentItemSize); | |||
RINOK(copyCoder->Code(inStream, outStream, NULL, NULL, progress)); | RINOK(copyCoder->Code(inStream, outStream, NULL, NULL, progress)); | |||
isOk = (copyCoderSpec->TotalSize == currentItemSize); | isOk = (copyCoderSpec->TotalSize == currentItemSize); | |||
} | } | |||
End of changes. 25 change blocks. | ||||
37 lines changed or deleted | 74 lines changed or added |