Skip to content

Commit

Permalink
Optimize utils and file parsing to prevent timeouts in exotic files (#…
Browse files Browse the repository at this point in the history
…772)

* utils: optimize replaceNonprintableChars()

It turns out it can be used quite often in fileformat.

* utils/system: replace custom sleep() with std::this_thread::sleep_for()

* utils/test.h: remove, not used anywhere

* utils/file_i: break long lines

* utils/dynamic_buffer: break long lines

* utils/const: remove, not used anywhere

* utils/alignment: break long lines

* utils/byte_value_storage: break long lines

* utils/conversion: replace toString(0 with std::to_string()

* utils/conversion: remove unused functions

* utils/conversion: reduce usage of numToStr()

* progress

* utils/conversion: refactor hex-string conversions

* fileformat: optimize PeFormat::scanForSectionAnomalies()

* pelib/ImportDirectory: add guard against infinite cycle

* capstone2llvmirtool: fix compilation, add std:: namespace
  • Loading branch information
PeterMatula committed May 23, 2020
1 parent 25cffa4 commit 64769c5
Show file tree
Hide file tree
Showing 95 changed files with 1,071 additions and 1,109 deletions.
2 changes: 1 addition & 1 deletion include/retdec/fileformat/file_format/pe/pe_format.h
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ class PeFormat : public FileFormat
/// @}
/// @name Auxiliary scanning methods
/// @{
void scanForSectionAnomalies();
void scanForSectionAnomalies(unsigned anamaliesLimit = 1000);
void scanForResourceAnomalies();
void scanForImportAnomalies();
void scanForExportAnomalies();
Expand Down
9 changes: 8 additions & 1 deletion include/retdec/pelib/ImportDirectory.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
#ifndef IMPORTDIRECTORY_H
#define IMPORTDIRECTORY_H

#include <set>

#include "retdec/pelib/PeLibAux.h"
#include "retdec/pelib/PeHeader.h"

Expand Down Expand Up @@ -699,6 +701,7 @@ namespace PeLib
}

// FirstThunk - IAT
std::set<dword> seenOffsets;
for (unsigned int i=0;i<vOldIidCurr.size();i++)
{
bool hasValidIlt = hasValidOriginalFirstThunk(vOldIidCurr[i].impdesc, peHeader);
Expand All @@ -708,7 +711,11 @@ namespace PeLib
{
return ERROR_INVALID_FILE;
}

if (seenOffsets.count(uiVaoft))
{
continue;
}
seenOffsets.insert(uiVaoft);
PELIB_THUNK_DATA<bits> tdCurr;

inStream_w.clear();
Expand Down
6 changes: 5 additions & 1 deletion include/retdec/utils/alignment.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,11 @@
namespace retdec {
namespace utils {

bool isAligned(std::uint64_t value, std::uint64_t alignment, std::uint64_t& remainder);
bool isAligned(
std::uint64_t value,
std::uint64_t alignment,
std::uint64_t& remainder);

std::uint64_t alignDown(std::uint64_t value, std::uint64_t alignment);
std::uint64_t alignUp(std::uint64_t value, std::uint64_t alignment);

Expand Down
226 changes: 178 additions & 48 deletions include/retdec/utils/byte_value_storage.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,24 @@ class ByteValueStorage
virtual std::size_t getNumberOfNibblesInByte() const = 0;
virtual bool hasMixedEndianForDouble() const = 0;

virtual bool getXByte(std::uint64_t address, std::uint64_t x, std::uint64_t& res, Endianness e = Endianness::UNKNOWN) const = 0;
virtual bool getXBytes(std::uint64_t address, std::uint64_t x, std::vector<std::uint8_t>& res) const = 0;

virtual bool setXByte(std::uint64_t address, std::uint64_t x, std::uint64_t val, Endianness e = Endianness::UNKNOWN) = 0;
virtual bool setXBytes(std::uint64_t address, const std::vector<std::uint8_t>& val) = 0;
virtual bool getXByte(
std::uint64_t address,
std::uint64_t x,
std::uint64_t& res,
Endianness e = Endianness::UNKNOWN) const = 0;
virtual bool getXBytes(
std::uint64_t address,
std::uint64_t x,
std::vector<std::uint8_t>& res) const = 0;

virtual bool setXByte(
std::uint64_t address,
std::uint64_t x,
std::uint64_t val,
Endianness e = Endianness::UNKNOWN) = 0;
virtual bool setXBytes(
std::uint64_t address,
const std::vector<std::uint8_t>& val) = 0;

Endianness getInverseEndianness() const;
bool isLittleEndian() const;
Expand All @@ -56,51 +69,168 @@ class ByteValueStorage
bool bitsToBig(std::vector<unsigned char>& values) const;
bool bitsToLittle(std::vector<unsigned char>& values) const;

bool get1Byte(std::uint64_t address, std::uint64_t& res, Endianness e = Endianness::UNKNOWN) const;
bool get2Byte(std::uint64_t address, std::uint64_t& res, Endianness e = Endianness::UNKNOWN) const;
bool get4Byte(std::uint64_t address, std::uint64_t& res, Endianness e = Endianness::UNKNOWN) const;
bool get8Byte(std::uint64_t address, std::uint64_t& res, Endianness e = Endianness::UNKNOWN) const;
bool get10Byte(std::uint64_t address, long double& res) const;
bool getWord(std::uint64_t address, std::uint64_t& res, Endianness e = Endianness::UNKNOWN) const;
bool getFloat(std::uint64_t address, float& res) const;
bool getDouble(std::uint64_t address, double& res) const;

bool set1Byte(std::uint64_t address, std::uint64_t val, Endianness e = Endianness::UNKNOWN);
bool set2Byte(std::uint64_t address, std::uint64_t val, Endianness e = Endianness::UNKNOWN);
bool set4Byte(std::uint64_t address, std::uint64_t val, Endianness e = Endianness::UNKNOWN);
bool set8Byte(std::uint64_t address, std::uint64_t val, Endianness e = Endianness::UNKNOWN);
bool set10Byte(std::uint64_t address, long double val);
bool setWord(std::uint64_t address, std::uint64_t val, Endianness e = Endianness::UNKNOWN);
bool setFloat(std::uint64_t address, float val);
bool setDouble(std::uint64_t address, double val);

bool getXByteArray(std::uint64_t address, std::uint64_t x, std::vector<std::uint64_t>& res, std::size_t size, Endianness e = Endianness::UNKNOWN) const;
bool get1ByteArray(std::uint64_t address, std::vector<std::uint64_t>& res, std::size_t size, Endianness e = Endianness::UNKNOWN) const;
bool get2ByteArray(std::uint64_t address, std::vector<std::uint64_t>& res, std::size_t size, Endianness e = Endianness::UNKNOWN) const;
bool get4ByteArray(std::uint64_t address, std::vector<std::uint64_t>& res, std::size_t size, Endianness e = Endianness::UNKNOWN) const;
bool get8ByteArray(std::uint64_t address, std::vector<std::uint64_t>& res, std::size_t size, Endianness e = Endianness::UNKNOWN) const;
bool get10ByteArray(std::uint64_t address, std::vector<long double>& res, std::size_t size) const;
bool getWordArray(std::uint64_t address, std::vector<std::uint64_t>& res, std::size_t, Endianness e = Endianness::UNKNOWN) const;
bool getFloatArray(std::uint64_t address, std::vector<float>& res, std::size_t size) const;
bool getDoubleArray(std::uint64_t address, std::vector<double>& res, std::size_t size) const;

bool getNTBS(std::uint64_t address, std::string& res, std::size_t size = 0) const;
bool getNTWS(std::uint64_t address, std::size_t width, std::vector<std::uint64_t>& res) const;
bool getNTWSNice(std::uint64_t address, std::size_t width, std::vector<std::uint64_t>& res) const;
bool get1Byte(
std::uint64_t address,
std::uint64_t& res,
Endianness e = Endianness::UNKNOWN) const;
bool get2Byte(
std::uint64_t address,
std::uint64_t& res,
Endianness e = Endianness::UNKNOWN) const;
bool get4Byte(
std::uint64_t address,
std::uint64_t& res,
Endianness e = Endianness::UNKNOWN) const;
bool get8Byte(
std::uint64_t address,
std::uint64_t& res,
Endianness e = Endianness::UNKNOWN) const;
bool get10Byte(
std::uint64_t address,
long double& res) const;
bool getWord(
std::uint64_t address,
std::uint64_t& res,
Endianness e = Endianness::UNKNOWN) const;
bool getFloat(
std::uint64_t address,
float& res) const;
bool getDouble(
std::uint64_t address,
double& res) const;

bool set1Byte(
std::uint64_t address,
std::uint64_t val,
Endianness e = Endianness::UNKNOWN);
bool set2Byte(
std::uint64_t address,
std::uint64_t val,
Endianness e = Endianness::UNKNOWN);
bool set4Byte(
std::uint64_t address,
std::uint64_t val,
Endianness e = Endianness::UNKNOWN);
bool set8Byte(
std::uint64_t address,
std::uint64_t val,
Endianness e = Endianness::UNKNOWN);
bool set10Byte(
std::uint64_t address,
long double val);
bool setWord(
std::uint64_t address,
std::uint64_t val,
Endianness e = Endianness::UNKNOWN);
bool setFloat(
std::uint64_t address,
float val);
bool setDouble(
std::uint64_t address,
double val);

bool getXByteArray(
std::uint64_t address,
std::uint64_t x,
std::vector<std::uint64_t>& res,
std::size_t size,
Endianness e = Endianness::UNKNOWN) const;
bool get1ByteArray(
std::uint64_t address,
std::vector<std::uint64_t>& res,
std::size_t size,
Endianness e = Endianness::UNKNOWN) const;
bool get2ByteArray(
std::uint64_t address,
std::vector<std::uint64_t>& res,
std::size_t size,
Endianness e = Endianness::UNKNOWN) const;
bool get4ByteArray(
std::uint64_t address,
std::vector<std::uint64_t>& res,
std::size_t size,
Endianness e = Endianness::UNKNOWN) const;
bool get8ByteArray(
std::uint64_t address,
std::vector<std::uint64_t>& res,
std::size_t size,
Endianness e = Endianness::UNKNOWN) const;
bool get10ByteArray(
std::uint64_t address,
std::vector<long double>& res,
std::size_t size) const;
bool getWordArray(
std::uint64_t address,
std::vector<std::uint64_t>& res,
std::size_t,
Endianness e = Endianness::UNKNOWN) const;
bool getFloatArray(
std::uint64_t address,
std::vector<float>& res, std::size_t size) const;
bool getDoubleArray(
std::uint64_t address,
std::vector<double>& res, std::size_t size) const;

bool getNTBS(
std::uint64_t address,
std::string& res,
std::size_t size = 0) const;
bool getNTWS(
std::uint64_t address,
std::size_t width,
std::vector<std::uint64_t>& res) const;
bool getNTWSNice(
std::uint64_t address,
std::size_t width,
std::vector<std::uint64_t>& res) const;

protected:
bool createValueFromBytes(const std::vector<std::uint8_t>& data, std::uint64_t& value, Endianness endian, std::uint64_t offset = 0, std::uint64_t size = 0) const;
bool createBytesFromValue(std::uint64_t data, std::uint64_t x, std::vector<std::uint8_t>& value, Endianness endian) const;

bool get10ByteImpl(const std::vector<std::uint8_t>& data, long double& res) const;
bool getFloatImpl(const std::vector<std::uint8_t>& data, float& res) const;
bool getDoubleImpl(const std::vector<std::uint8_t>& data, double& res) const;

using GetNByteFn = std::function<bool(std::uint64_t, std::uint64_t&, Endianness)>;
using GetXByteFn = std::function<bool(std::uint64_t, std::uint64_t, std::uint64_t&, Endianness)>;
bool getNTBSImpl(const GetNByteFn& get1ByteFn, std::uint64_t address, std::string& res, std::size_t size) const;
bool getNTWSImpl(const GetXByteFn& getXByteFn, std::uint64_t address, std::size_t width, std::vector<std::uint64_t>& res) const;
bool getNTWSNiceImpl(const GetXByteFn& getXByteFn, std::uint64_t address, std::size_t width, std::vector<std::uint64_t>& res) const;
bool createValueFromBytes(
const std::vector<std::uint8_t>& data,
std::uint64_t& value,
Endianness endian,
std::uint64_t offset = 0,
std::uint64_t size = 0) const;
bool createBytesFromValue(
std::uint64_t data,
std::uint64_t x,
std::vector<std::uint8_t>& value,
Endianness endian) const;

bool get10ByteImpl(
const std::vector<std::uint8_t>& data,
long double& res) const;
bool getFloatImpl(
const std::vector<std::uint8_t>& data,
float& res) const;
bool getDoubleImpl(
const std::vector<std::uint8_t>& data,
double& res) const;

using GetNByteFn = std::function<bool(
std::uint64_t,
std::uint64_t&,
Endianness)>;
using GetXByteFn = std::function<bool(
std::uint64_t,
std::uint64_t,
std::uint64_t&, Endianness)>;

bool getNTBSImpl(
const GetNByteFn& get1ByteFn,
std::uint64_t address,
std::string& res,
std::size_t size) const;
bool getNTWSImpl(
const GetXByteFn& getXByteFn,
std::uint64_t address,
std::size_t width,
std::vector<std::uint64_t>& res) const;
bool getNTWSNiceImpl(
const GetXByteFn& getXByteFn,
std::uint64_t address,
std::size_t width,
std::vector<std::uint64_t>& res) const;
};

} // namespace utils
Expand Down
73 changes: 0 additions & 73 deletions include/retdec/utils/const.h

This file was deleted.

Loading

0 comments on commit 64769c5

Please sign in to comment.