Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Lz high memory usage #818

Merged
merged 2 commits into from
Jul 23, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 15 additions & 11 deletions include/retdec/pelib/DelayImportDirectory.h
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ namespace PeLib
init();

// Keep loading until we encounter an entry filles with zeros
for(std::size_t i = 0;; i += sizeof(PELIB_IMAGE_DELAY_LOAD_DESCRIPTOR))
for(std::uint32_t i = 0;; i += sizeof(PELIB_IMAGE_DELAY_LOAD_DESCRIPTOR))
{
PELIB_IMAGE_DELAY_IMPORT_DIRECTORY_RECORD rec;

Expand All @@ -123,6 +123,10 @@ namespace PeLib
if(imageLoader.getImageBitability() == 32 && (rec.delayedImport.Attributes & PELIB_DELAY_ATTRIBUTE_V2) == 0)
normalize32BitDelayImport(rec.delayedImport, (std::uint32_t)imageBase);

// Stop on blatantly invalid delay import entries (old PELIB behavior)
if(rec.delayedImport.DelayImportNameTableRva >= sizeOfImage || rec.delayedImport.DelayImportAddressTableRva >= sizeOfImage)
return ERROR_INVALID_FILE;

// Get name of library
imageLoader.readString(rec.Name, rec.delayedImport.NameRva, IMPORT_LIBRARY_MAX_LENGTH);

Expand All @@ -131,16 +135,16 @@ namespace PeLib
//

std::vector<uint64_t> nameAddresses;
std::uint32_t rva = rec.delayedImport.DelayImportNameTableRva;
std::uint32_t rva2 = rec.delayedImport.DelayImportNameTableRva;

for(;;)
{
std::uint64_t nameAddress;

// Read single name address
if(imageLoader.readPointer(rva, nameAddress) != pointerSize)
break;
rva += pointerSize;
// Read single name address. Also stop processing if the RVA gets out of image
if(imageLoader.readPointer(rva2, nameAddress) != pointerSize)
return ERROR_INVALID_FILE;
rva2 += pointerSize;

// Value of zero means that this is the end of the bound import name table
if(nameAddress == 0)
Expand All @@ -153,17 +157,17 @@ namespace PeLib
//

std::vector<uint64_t> funcAddresses;
rva = rec.delayedImport.DelayImportAddressTableRva;
rva2 = rec.delayedImport.DelayImportAddressTableRva;

// Read all (VAs) of import names
for (std::size_t i = 0; i < nameAddresses.size(); i++)
{
std::uint64_t funcAddress;

// Read single name address
if(imageLoader.readPointer(rva, funcAddress) != pointerSize)
break;
rva += pointerSize;
// Read single name address. Also stop processing if the RVA gets out of image
if(imageLoader.readPointer(rva2, funcAddress) != pointerSize)
return ERROR_INVALID_FILE;
rva2 += pointerSize;

// Value of zero means that this is the end of the bound import name table
if(funcAddress == 0)
Expand Down
2 changes: 1 addition & 1 deletion src/pelib/BoundImportDirectory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,7 @@ namespace PeLib
std::uint32_t importSize = imageLoader.getDataDirSize(PELIB_IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT);
std::uint32_t sizeOfImage = imageLoader.getSizeOfImage();

if(importRva > sizeOfImage || (importRva > importSize) > sizeOfImage)
if(importRva >= sizeOfImage || (importRva + importSize) >= sizeOfImage)
{
return ERROR_INVALID_FILE;
}
Expand Down
6 changes: 2 additions & 4 deletions src/pelib/ImageLoader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -210,9 +210,9 @@ uint32_t PeLib::ImageLoader::stringLength(
const uint8_t * dataPtr;
uint32_t rvaEndPage = (pageIndex + 1) * PELIB_PAGE_SIZE;

// If zero page, means we found an RVA with zero
// If zero page, means this is a zeroed page. This is the end of the string.
if(page.buffer.empty())
return rva;
break;
dataBegin = dataPtr = page.buffer.data() + (rva & (PELIB_PAGE_SIZE - 1));

// Perhaps the last page loaded?
Expand Down Expand Up @@ -445,8 +445,6 @@ uint32_t PeLib::ImageLoader::getFileOffsetFromRva(uint32_t rva) const
// For multi-section images, real pointer to raw data is aligned down to sector size
if(optionalHeader.SectionAlignment >= PELIB_PAGE_SIZE)
realPointerToRawData = realPointerToRawData & ~(PELIB_SECTOR_SIZE - 1);
if(optionalHeader.SectionAlignment != 0)
sectionRvaStart = AlignToSize(sectHdr.VirtualAddress, optionalHeader.SectionAlignment);

// Is the RVA inside that section?
if(sectionRvaStart <= rva && rva < (sectionRvaStart + virtualSize))
Expand Down
8 changes: 5 additions & 3 deletions src/pelib/ResourceDirectory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -330,11 +330,13 @@ namespace PeLib
m_data.clear();

// No data or invalid leaf
if(entry.OffsetToData >= sizeOfImage || entry.OffsetToData + entry.Size > sizeOfImage)
if(entry.OffsetToData > sizeOfImage || entry.Size > sizeOfImage)
return ERROR_NONE;
if((uiRsrcRva + entry.OffsetToData) >= sizeOfImage || (uiRsrcRva + entry.OffsetToData + entry.Size) > sizeOfImage)
return ERROR_NONE;

// Data pointing before resource directory?
if((uiRsrcRva + entry.OffsetToData) < uiRsrcRva)
// Data range overflow?
if((uiRsrcRva + entry.OffsetToData) < uiRsrcRva || (uiRsrcRva + entry.OffsetToData + entry.Size) < uiRsrcRva)
return ERROR_NONE;

// Load the resource data
Expand Down