src: introduce type tribool

This commit is contained in:
Markus F.X.J. Oberhumer 2023-08-15 14:44:50 +02:00
parent 10e759f1f1
commit a9ac4b5e23
51 changed files with 228 additions and 120 deletions

View File

@ -863,11 +863,11 @@ int upx_test_overlap ( const upx_bytep buf,
#include "util/snprintf.h" // must get included first!
#include "util/util.h"
#include "options.h"
#include "except.h"
#include "bele.h"
#include "console/console.h"
#include "util/util.h"
// xspan
#include "util/raw_bytes.h"
#include "util/xspan.h"

View File

@ -109,7 +109,7 @@ struct PackerNames {
names[names_count].sname = pb->getName();
names_count++;
}
static bool visit(PackerBase *pb, void *user) {
static tribool visit(PackerBase *pb, void *user) {
PackerNames *self = (PackerNames *) user;
self->add(pb);
return false;

View File

@ -679,8 +679,11 @@ static int do_option(int optc, const char *arg) {
break;
case 632:
opt->win32_pe.compress_resources = 1;
if (mfx_optarg && mfx_optarg[0])
getoptvar(&opt->win32_pe.compress_resources, 0, 1, arg);
if (mfx_optarg && mfx_optarg[0]) {
int value;
getoptvar(&value, 0, 1, arg);
opt->win32_pe.compress_resources = bool(value);
}
// printf("compress_resources: %d\n", opt->win32_pe.compress_resources);
break;
case 633:

View File

@ -163,8 +163,8 @@ struct Options final {
struct {
int compress_exports;
int compress_icons;
int compress_resources;
signed char compress_rt[25]; // 25 == RT_LAST
TriBool<upx_int8_t> compress_resources;
TriBool<upx_int8_t> compress_rt[25]; // 25 == RT_LAST
int strip_relocs;
const char *keep_resource;
} win32_pe;

View File

@ -58,7 +58,7 @@ const int *PackCom::getFilters() const {
//
**************************************************************************/
bool PackCom::canPack() {
tribool PackCom::canPack() {
byte buf[128];
fi->readx(buf, sizeof(buf));
@ -197,7 +197,7 @@ void PackCom::pack(OutputFile *fo) {
//
**************************************************************************/
int PackCom::canUnpack() {
tribool PackCom::canUnpack() {
if (!readPackHeader(128)) // read "ph"
return false;
if (file_size_u <= ph.c_len)

View File

@ -46,8 +46,8 @@ public:
virtual void pack(OutputFile *fo) override;
virtual void unpack(OutputFile *fo) override;
virtual bool canPack() override;
virtual int canUnpack() override;
virtual tribool canPack() override;
virtual tribool canUnpack() override;
protected:
virtual Linker *newLinker() const override;

View File

@ -197,7 +197,7 @@ void PackDjgpp2::stripDebug() {
//
**************************************************************************/
bool PackDjgpp2::canPack() {
tribool PackDjgpp2::canPack() {
if (!readFileHeader())
return false;
if (is_dlm(fi, coff_offset))
@ -346,7 +346,7 @@ void PackDjgpp2::pack(OutputFile *fo) {
//
**************************************************************************/
int PackDjgpp2::canUnpack() {
tribool PackDjgpp2::canUnpack() {
if (!readFileHeader())
return false;
if (is_dlm(fi, coff_offset))

View File

@ -50,8 +50,8 @@ public:
virtual void pack(OutputFile *fo) override;
virtual void unpack(OutputFile *fo) override;
virtual bool canPack() override;
virtual int canUnpack() override;
virtual tribool canPack() override;
virtual tribool canUnpack() override;
protected:
void handleStub(OutputFile *fo);

View File

@ -229,7 +229,7 @@ int PackExe::readFileHeader() {
return UPX_F_DOS_EXE;
}
bool PackExe::canPack() {
tribool PackExe::canPack() {
if (fn_has_ext(fi->getName(), "sys")) // dos/sys
return false;
if (!readFileHeader())
@ -572,7 +572,7 @@ void PackExe::pack(OutputFile *fo) {
//
**************************************************************************/
int PackExe::canUnpack() {
tribool PackExe::canUnpack() {
if (!readFileHeader())
return false;
const unsigned off = ih.headsize16 * 16;

View File

@ -46,8 +46,8 @@ public:
virtual void pack(OutputFile *fo) override;
virtual void unpack(OutputFile *fo) override;
virtual bool canPack() override;
virtual int canUnpack() override;
virtual tribool canPack() override;
virtual tribool canUnpack() override;
// unpacker capabilities
virtual bool canUnpackVersion(int version) const override {

View File

@ -2411,7 +2411,7 @@ bool PackLinuxElf32::calls_crt1(Elf32_Rel const *rel, int sz)
return false;
}
int PackLinuxElf32::canUnpack() // bool, except -1: format known, but not packed
tribool PackLinuxElf32::canUnpack() // bool, except -1: format known, but not packed
{
if (checkEhdr(&ehdri)) {
return false;
@ -2506,7 +2506,7 @@ PackLinuxElf32::canPackOSABI(Elf32_Ehdr const *ehdr)
return true; // good so far
}
bool PackLinuxElf32::canPack()
tribool PackLinuxElf32::canPack()
{
union {
unsigned char buf[MAX_ELF_HDR_32];
@ -2589,7 +2589,7 @@ bool PackLinuxElf32::canPack()
max_offset = UPX_MAX(max_offset, get_te32(&phdr->p_filesz) + get_te32(&phdr->p_offset));
}
}
if (canUnpack() > 0) {
if (canUnpack()) {
throwAlreadyPacked();
}
// We want to compress position-independent executable (gcc -pie)
@ -2952,7 +2952,7 @@ proceed: ;
return true;
}
int PackLinuxElf64::canUnpack() // bool, except -1: format known, but not packed
tribool PackLinuxElf64::canUnpack() // bool, except -1: format known, but not packed
{
if (checkEhdr(&ehdri)) {
return false;
@ -2966,7 +2966,7 @@ int PackLinuxElf64::canUnpack() // bool, except -1: format known, but not packed
return false;
}
bool
tribool
PackLinuxElf64::canPack()
{
union {
@ -3024,7 +3024,7 @@ PackLinuxElf64::canPack()
max_offset = UPX_MAX(max_offset, get_te64(&phdr->p_filesz) + get_te64(&phdr->p_offset));
}
}
if (canUnpack() > 0) {
if (canUnpack()) {
throwAlreadyPacked();
}
// We want to compress position-independent executable (gcc -pie)
@ -7407,7 +7407,7 @@ PackLinuxElf32x86::~PackLinuxElf32x86()
{
}
int PackLinuxElf32x86::canUnpack() // bool, except -1: format known, but not packed
tribool PackLinuxElf32x86::canUnpack() // bool, except -1: format known, but not packed
{
if (super::canUnpack()) {
return true;

View File

@ -46,7 +46,7 @@ public:
/*virtual void buildLoader(const Filter *);*/
virtual int getVersion() const override { return 14; } // upx-3.96 cannot upack, for instance
virtual bool canUnpackVersion(int version) const override { return (version >= 11); }
virtual int canUnpack() override { return super::canUnpack(); } // bool, except -1: format known, but not packed
virtual tribool canUnpack() override { return super::canUnpack(); } // bool, except -1: format known, but not packed
protected:
virtual const int *getCompressionMethods(int method, int level) const override;
@ -140,8 +140,8 @@ protected:
virtual void PackLinuxElf32help1(InputFile *f);
virtual int checkEhdr(Elf32_Ehdr const *ehdr) const;
virtual bool canPackOSABI(Elf32_Ehdr const *);
virtual bool canPack() override;
virtual int canUnpack() override; // bool, except -1: format known, but not packed
virtual tribool canPack() override;
virtual tribool canUnpack() override; // bool, except -1: format known, but not packed
// These ARM routines are essentially common to big/little endian,
// but the class hierarchy splits after this class.
@ -311,8 +311,8 @@ public:
protected:
virtual void PackLinuxElf64help1(InputFile *f);
virtual int checkEhdr(Elf64_Ehdr const *ehdr) const;
virtual bool canPack() override;
virtual int canUnpack() override; // bool, except -1: format known, but not packed
virtual tribool canPack() override;
virtual tribool canUnpack() override; // bool, except -1: format known, but not packed
virtual void pack1(OutputFile *, Filter &) override; // generate executable header
virtual void asl_pack2_Shdrs(OutputFile *, unsigned pre_xct_top); // AndroidSharedLibrary processes Shdrs
@ -606,7 +606,7 @@ public:
virtual const char *getName() const override { return "linux/i386"; }
virtual const char *getFullName(const options_t *) const override { return "i386-linux.elf"; }
virtual const int *getFilters() const override;
virtual int canUnpack() override; // bool, except -1: format known, but not packed
virtual tribool canUnpack() override; // bool, except -1: format known, but not packed
protected:
virtual void pack1(OutputFile *, Filter &) override; // generate executable header

View File

@ -495,7 +495,7 @@ int PackLinuxI386::checkEhdr(const Elf_LE32_Ehdr *ehdr) const
//
**************************************************************************/
bool PackLinuxI386::canPack()
tribool PackLinuxI386::canPack()
{
if (exetype != 0)
return super::canPack();

View File

@ -54,7 +54,7 @@ public:
virtual const int *getFilters() const override;
virtual void buildLoader(const Filter *) override;
virtual bool canPack() override;
virtual tribool canPack() override;
protected:
virtual void pack1(OutputFile *, Filter &) override; // generate executable header

View File

@ -64,7 +64,7 @@ PackLinuxElf32x86interp::~PackLinuxElf32x86interp()
{
}
bool PackLinuxElf32x86interp::canPack()
tribool PackLinuxElf32x86interp::canPack()
{
if (opt->o_unix.make_ptinterp) {
return true;

View File

@ -49,7 +49,7 @@ public:
virtual const char *getName() const override { return "linux/elfi386"; }
virtual const char *getFullName(const options_t *) const override { return "i386-linux.elf.interp"; }
virtual bool canPack() override;
virtual tribool canPack() override;
virtual void unpack(OutputFile *fo) override;
protected:

View File

@ -122,7 +122,7 @@ bool PackLinuxI386sh::getShellName(char *buf)
return false;
for (int j = 0; nullptr != shname[j]; ++j) {
if (0 == strcmp(shname[j], bname + 1)) {
bool const s = super::canPack();
bool const s = bool(super::canPack());
if (s) {
opt->o_unix.blocksize = blocksize = file_size;
}
@ -138,7 +138,7 @@ bool PackLinuxI386sh::getShellName(char *buf)
}
bool PackLinuxI386sh::canPack()
tribool PackLinuxI386sh::canPack()
{
#if defined(__linux__) //{
// only compress i386sh scripts when running under Linux

View File

@ -54,7 +54,7 @@ public:
virtual void pack1(OutputFile *fo, Filter &ft) override;
virtual off_t pack3(OutputFile *fo, Filter &ft) override;
virtual bool canPack() override;
virtual tribool canPack() override;
// virtual void unpack(OutputFile *fo) { super::unpack(fo); }
virtual bool canUnpackVersion(int version) const override
{ return (version >= 11); }

View File

@ -1615,7 +1615,7 @@ void PackMachBase<T>::unpack(OutputFile *fo)
// The prize is the value of overlay_offset: the offset of compressed data
template <class T>
int PackMachBase<T>::canUnpack()
tribool PackMachBase<T>::canUnpack()
{
unsigned const lc_seg = lc_seg_info[sizeof(Addr)>>3].segment_cmd;
fi->seek(0, SEEK_SET);
@ -1924,7 +1924,7 @@ upx_uint64_t PackMachBase<T>::get_mod_init_func(Mach_segment_command const *segp
}
template <class T>
bool PackMachBase<T>::canPack()
tribool PackMachBase<T>::canPack()
{
unsigned const lc_seg = lc_seg_info[sizeof(Addr)>>3].segment_cmd;
fi->seek(0, SEEK_SET);
@ -2484,7 +2484,7 @@ void PackMachFat::unpack(OutputFile *fo)
}
}
bool PackMachFat::canPack()
tribool PackMachFat::canPack()
{
struct Mach_fat_arch const *const arch = &fat_head.arch[0];
@ -2552,7 +2552,7 @@ bool PackMachFat::canPack()
return true;
}
int PackMachFat::canUnpack()
tribool PackMachFat::canUnpack()
{
struct Mach_fat_arch const *const arch = &fat_head.arch[0];

View File

@ -756,8 +756,8 @@ public:
virtual void pack1_setup_threado(OutputFile *const fo) = 0;
virtual void unpack(OutputFile *fo) override;
virtual bool canPack() override;
virtual int canUnpack() override;
virtual tribool canPack() override;
virtual tribool canUnpack() override;
virtual upx_uint64_t get_mod_init_func(Mach_segment_command const *segptr);
virtual unsigned find_SEGMENT_gap(unsigned const k, unsigned pos_eof);
@ -1257,8 +1257,8 @@ protected:
virtual void list() override;
public:
virtual bool canPack() override;
virtual int canUnpack() override;
virtual tribool canPack() override;
virtual tribool canUnpack() override;
protected:
// loader core

View File

@ -220,7 +220,7 @@ bool PackPs1::checkFileHeader() {
//
**************************************************************************/
bool PackPs1::canPack() {
tribool PackPs1::canPack() {
byte buf[PS_HDR_SIZE - sizeof(ps1_exe_t)];
if (!readFileHeader())
@ -614,7 +614,7 @@ void PackPs1::pack(OutputFile *fo) {
//
**************************************************************************/
int PackPs1::canUnpack() {
tribool PackPs1::canUnpack() {
if (!readFileHeader())
return false;
if (!readPackHeader(CD_SEC))

View File

@ -50,8 +50,8 @@ public:
virtual void pack(OutputFile *fo) override;
virtual void unpack(OutputFile *fo) override;
virtual bool canPack() override;
virtual int canUnpack() override;
virtual tribool canPack() override;
virtual tribool canUnpack() override;
protected:
void putBkupHeader(const byte *src, byte *dst, unsigned *len);

View File

@ -40,7 +40,7 @@ static const CLANG_FORMAT_DUMMY_STATEMENT
//
**************************************************************************/
bool PackSys::canPack() {
tribool PackSys::canPack() {
byte buf[128];
fi->readx(buf, sizeof(buf));

View File

@ -41,7 +41,7 @@ public:
virtual const char *getName() const override { return "dos/sys"; }
virtual const char *getFullName(const Options *) const override { return "i086-dos16.sys"; }
virtual bool canPack() override;
virtual tribool canPack() override;
protected: // dos/com overrides
virtual unsigned getCallTrickOffset() const override { return 0; }

View File

@ -150,7 +150,7 @@ int PackTmt::readFileHeader() {
#undef H
}
bool PackTmt::canPack() {
tribool PackTmt::canPack() {
if (!readFileHeader())
return false;
return true;
@ -265,7 +265,7 @@ void PackTmt::pack(OutputFile *fo) {
throwNotCompressible();
}
int PackTmt::canUnpack() {
tribool PackTmt::canUnpack() {
if (!readFileHeader())
return false;
fi->seek(adam_offset, SEEK_SET);

View File

@ -48,8 +48,8 @@ public:
virtual void pack(OutputFile *fo) override;
virtual void unpack(OutputFile *fo) override;
virtual bool canPack() override;
virtual int canUnpack() override;
virtual tribool canPack() override;
virtual tribool canUnpack() override;
protected:
int readFileHeader();

View File

@ -342,7 +342,7 @@ static bool check_relocs(const byte *relocs, unsigned rsize, unsigned image_size
//
**************************************************************************/
bool PackTos::canPack() {
tribool PackTos::canPack() {
if (!readFileHeader())
return false;
@ -673,7 +673,7 @@ void PackTos::pack(OutputFile *fo) {
//
**************************************************************************/
int PackTos::canUnpack() {
tribool PackTos::canUnpack() {
if (!readFileHeader())
return false;
if (!readPackHeader(768))

View File

@ -46,8 +46,8 @@ public:
virtual void pack(OutputFile *fo) override;
virtual void unpack(OutputFile *fo) override;
virtual bool canPack() override;
virtual int canUnpack() override;
virtual tribool canPack() override;
virtual tribool canUnpack() override;
virtual void fileInfo() override;

View File

@ -67,7 +67,7 @@ PackUnix::~PackUnix()
}
// common part of canPack(), enhanced by subclasses
bool PackUnix::canPack()
tribool PackUnix::canPack()
{
if (exetype == 0)
return false;
@ -555,7 +555,7 @@ unsigned PackUnix::unpackExtent(unsigned wanted, OutputFile *fo,
**************************************************************************/
// The prize is the value of overlay_offset: the offset of compressed data
int PackUnix::canUnpack()
tribool PackUnix::canUnpack()
{
int const small = 32 + sizeof(overlay_offset);
// Allow zero-filled last page, for Mac OS X code signing.

View File

@ -55,8 +55,8 @@ public:
virtual void pack(OutputFile *fo) override;
virtual void unpack(OutputFile *fo) override;
virtual bool canPack() override;
virtual int canUnpack() override; // bool, except -1: format known, but not packed
virtual tribool canPack() override;
virtual tribool canUnpack() override; // bool, except -1: format known, but not packed
int find_overlay_offset(MemBuffer const &buf);
protected:

View File

@ -143,7 +143,7 @@ typename T::Shdr const *PackVmlinuxBase<T>::getElfSections()
}
template <class T>
bool PackVmlinuxBase<T>::canPack()
tribool PackVmlinuxBase<T>::canPack()
{
fi->seek(0, SEEK_SET);
fi->readx(&ehdri, sizeof(ehdri));
@ -553,7 +553,7 @@ void PackVmlinuxBase<T>::pack(OutputFile *fo)
}
template <class T>
int PackVmlinuxBase<T>::canUnpack()
tribool PackVmlinuxBase<T>::canUnpack()
{
fi->seek(0, SEEK_SET);
fi->readx(&ehdri, sizeof(ehdri));

View File

@ -83,9 +83,9 @@ protected:
virtual int getStrategy(Filter &/*ft*/);
virtual bool is_valid_e_entry(Addr) = 0;
virtual bool has_valid_vmlinux_head() = 0;
virtual bool canPack() override;
virtual tribool canPack() override;
virtual void pack(OutputFile *fo) override;
virtual int canUnpack() override; // bool, except -1: format known, but not packed
virtual tribool canUnpack() override; // bool, except -1: format known, but not packed
virtual void unpack(OutputFile *fo) override;
virtual unsigned write_vmlinux_head(
OutputFile *fo,

View File

@ -93,7 +93,7 @@ int PackVmlinuzI386::getStrategy(Filter &/*ft*/)
}
bool PackVmlinuzI386::canPack()
tribool PackVmlinuzI386::canPack()
{
return readFileHeader() == getFormat();
}
@ -671,7 +671,7 @@ void PackBvmlinuzI386::pack(OutputFile *fo)
// unpack
**************************************************************************/
int PackVmlinuzI386::canUnpack()
tribool PackVmlinuzI386::canUnpack()
{
if (readFileHeader() != getFormat())
return false;
@ -735,7 +735,7 @@ int PackVmlinuzARMEL::getStrategy(Filter &/*ft*/)
return (opt->no_filter ? -3 : ((opt->filter > 0) ? -2 : 2));
}
bool PackVmlinuzARMEL::canPack()
tribool PackVmlinuzARMEL::canPack()
{
return readFileHeader() == getFormat();
}
@ -1029,7 +1029,7 @@ void PackVmlinuzARMEL::pack(OutputFile *fo)
throwNotCompressible();
}
int PackVmlinuzARMEL::canUnpack()
tribool PackVmlinuzARMEL::canUnpack()
{
if (readFileHeader() != getFormat())
return false;

View File

@ -51,8 +51,8 @@ public:
virtual void pack(OutputFile *fo) override;
virtual void unpack(OutputFile *fo) override;
virtual bool canPack() override;
virtual int canUnpack() override;
virtual tribool canPack() override;
virtual tribool canUnpack() override;
protected:
virtual int readFileHeader();
@ -142,8 +142,8 @@ public:
virtual void pack(OutputFile *fo) override;
virtual void unpack(OutputFile *fo) override;
virtual bool canPack() override;
virtual int canUnpack() override;
virtual tribool canPack() override;
virtual tribool canUnpack() override;
protected:
virtual int readFileHeader();

View File

@ -75,7 +75,7 @@ int PackW32PeI386::readFileHeader() {
// pack
**************************************************************************/
bool PackW32PeI386::canPack() {
tribool PackW32PeI386::canPack() {
if (!readFileHeader())
return false;
checkMachine(ih.cpu);

View File

@ -51,7 +51,7 @@ public:
virtual void setOhHeaderSize(const pe_section_t *osection) override;
virtual void pack(OutputFile *fo) override;
virtual bool canPack() override;
virtual tribool canPack() override;
protected:
virtual int readFileHeader() override;

View File

@ -65,7 +65,7 @@ Linker *PackW64PeAmd64::newLinker() const { return new ElfLinkerAMD64; }
// pack
**************************************************************************/
bool PackW64PeAmd64::canPack() {
tribool PackW64PeAmd64::canPack() {
if (!readFileHeader())
return false;
checkMachine(ih.cpu);

View File

@ -50,7 +50,7 @@ public:
virtual void setOhHeaderSize(const pe_section_t *osection) override;
virtual void pack(OutputFile *fo) override;
virtual bool canPack() override;
virtual tribool canPack() override;
protected:
virtual void buildLoader(const Filter *ft) override;

View File

@ -59,7 +59,7 @@ const int *PackW64PeArm64::getFilters() const { return nullptr; }
// pack
**************************************************************************/
bool PackW64PeArm64::canPack() {
tribool PackW64PeArm64::canPack() {
if (!readFileHeader())
return false;
checkMachine(ih.cpu);
@ -106,7 +106,7 @@ void PackW64PeArm64::pack(OutputFile *fo) {
// pack
**************************************************************************/
bool PackW64PeArm64EC::canPack() {
tribool PackW64PeArm64EC::canPack() {
if (!readFileHeader())
return false;
checkMachine(ih.cpu);

View File

@ -50,7 +50,7 @@ public:
virtual void setOhHeaderSize(const pe_section_t *osection) override;
virtual void pack(OutputFile *fo) override;
virtual bool canPack() override;
virtual tribool canPack() override;
protected:
virtual void buildLoader(const Filter *ft) override;
@ -74,7 +74,7 @@ public:
virtual const char *getName() const override { return "win64/arm64ec"; }
virtual const char *getFullName(const Options *) const override { return "arm64ec-win64.pe"; }
virtual bool canPack() override;
virtual tribool canPack() override;
};
/* vim:set ts=4 sw=4 et: */

View File

@ -112,7 +112,7 @@ void PackWcle::handleStub(OutputFile *fo) {
Packer::handleStub(fi, fo, le_offset);
}
bool PackWcle::canPack() {
tribool PackWcle::canPack() {
if (!LeFile::readFileHeader())
return false;
return true;
@ -731,7 +731,7 @@ void PackWcle::decodeEntryTable() {
ientries = nullptr;
}
int PackWcle::canUnpack() {
tribool PackWcle::canUnpack() {
if (!LeFile::readFileHeader())
return false;
fi->seek(exe_offset + ih.data_pages_offset, SEEK_SET);

View File

@ -48,8 +48,8 @@ public:
virtual void pack(OutputFile *fo) override;
virtual void unpack(OutputFile *fo) override;
virtual bool canPack() override;
virtual int canUnpack() override;
virtual tribool canPack() override;
virtual tribool canUnpack() override;
protected:
virtual void handleStub(OutputFile *fo);

View File

@ -111,7 +111,7 @@ void PackWinCeArm::processTls(Interval *) // pass 1
// pack
**************************************************************************/
bool PackWinCeArm::canPack() {
tribool PackWinCeArm::canPack() {
if (!readFileHeader())
return false;
checkMachine(ih.cpu);

View File

@ -55,7 +55,7 @@ public:
virtual void setOhHeaderSize(const pe_section_t *osection) override;
virtual void pack(OutputFile *fo) override;
virtual bool canPack() override;
virtual tribool canPack() override;
protected:
virtual void buildLoader(const Filter *ft) override;

View File

@ -57,12 +57,14 @@ public:
virtual const int *getCompressionMethods(int method, int level) const = 0;
virtual const int *getFilters() const = 0;
// canPack() should throw a cantPackException eplaining why it
// cannot pack a recognized format.
virtual bool canPack() = 0;
// canUnpack() can return -1 meaning "format recognized, but file
// is definitely not packed". See packmast.cpp try_unpack().
virtual int canUnpack() = 0;
// canPack() should throw a cantPackException eplaining why it cannot pack
// a recognized format.
// canPack() can return -1 to stop early; see class PackMaster
virtual tribool canPack() = 0;
// canUnpack() should throw a cantUnpackException eplaining why it cannot pack
// a recognized format.
// canUnpack() can return -1 to stop early; see class PackMaster
virtual tribool canUnpack() = 0;
// PackMaster entries
virtual void assertPacker() const = 0;
@ -164,10 +166,10 @@ protected:
void verifyOverlappingDecompression(byte *o_ptr, unsigned o_size, Filter *ft = nullptr);
// packheader handling
virtual int patchPackHeader(void *b, int blen);
virtual bool getPackHeader(const void *b, int blen, bool allow_incompressible = false);
virtual bool readPackHeader(int len, bool allow_incompressible = false);
virtual void checkAlreadyPacked(const void *b, int blen);
virtual int patchPackHeader(void *b, int blen) final;
virtual bool getPackHeader(const void *b, int blen, bool allow_incompressible = false) final;
virtual bool readPackHeader(int len, bool allow_incompressible = false) final;
virtual void checkAlreadyPacked(const void *b, int blen) final;
// loader core
virtual void buildLoader(const Filter *ft) = 0;

View File

@ -89,37 +89,38 @@ PackMaster::~PackMaster() noexcept {
//
**************************************************************************/
static bool try_can_pack(PackerBase *pb, void *user) may_throw {
static tribool try_can_pack(PackerBase *pb, void *user) may_throw {
InputFile *f = (InputFile *) user;
try {
pb->initPackHeader();
f->seek(0, SEEK_SET);
if (pb->canPack()) {
tribool r = pb->canPack();
if (r) {
if (opt->cmd == CMD_COMPRESS)
pb->updatePackHeader();
f->seek(0, SEEK_SET);
return true;
return true; // success
}
if (r.isOther()) // aka "-1"
return r; // canPack() says the format is recognized and we should stop early
} catch (const IOException &) {
// ignored
}
return false;
}
static bool try_can_unpack(PackerBase *pb, void *user) may_throw {
static tribool try_can_unpack(PackerBase *pb, void *user) may_throw {
InputFile *f = (InputFile *) user;
try {
pb->initPackHeader();
f->seek(0, SEEK_SET);
int r = pb->canUnpack();
if (r > 0) {
tribool r = pb->canUnpack();
if (r) {
f->seek(0, SEEK_SET);
return true;
}
if (r < 0) {
// FIXME - could stop testing all other unpackers at this time
// see canUnpack() in packer.h
return true; // success
}
if (r.isOther()) // aka "-1"
return r; // canUnpack() says the format is recognized and we should stop early
} catch (const IOException &) {
// ignored
}
@ -141,8 +142,11 @@ PackerBase *PackMaster::visitAllPackers(visit_func_t func, InputFile *f, const O
if (o->debug.debug_level) \
fprintf(stderr, "visitAllPackers: (ver=%d, fmt=%3d) %s\n", pb->getVersion(), \
pb->getFormat(), #Klass); \
if (func(pb.get(), user)) \
return pb.release(); \
tribool r = func(pb.get(), user); \
if (r) \
return pb.release(); /* success */ \
if (r.isOther()) \
return nullptr; /* stop early */ \
ACC_BLOCK_END
// NOTE: order of tries is important !!!

View File

@ -46,7 +46,7 @@ public:
void list();
void fileInfo();
typedef bool (*visit_func_t)(PackerBase *pb, void *user);
typedef tribool (*visit_func_t)(PackerBase *pb, void *user);
static PackerBase *visitAllPackers(visit_func_t, InputFile *f, const Options *, void *user)
may_throw;

View File

@ -1795,14 +1795,14 @@ void PeFile::processResources(Resource *res) {
return;
// setup default options for resource compression
if (opt->win32_pe.compress_resources < 0)
if (opt->win32_pe.compress_resources.isOther())
opt->win32_pe.compress_resources = !isefi;
if (!opt->win32_pe.compress_resources) {
opt->win32_pe.compress_icons = false;
for (int i = 0; i < RT_LAST; i++)
opt->win32_pe.compress_rt[i] = false;
}
if (opt->win32_pe.compress_rt[RT_STRING] < 0) {
if (opt->win32_pe.compress_rt[RT_STRING].isOther()) {
// by default, don't compress RT_STRINGs of screensavers (".scr")
opt->win32_pe.compress_rt[RT_STRING] = true;
if (fn_has_ext(fi->getName(), "scr"))
@ -3017,7 +3017,7 @@ void PeFile32::unpack(OutputFile *fo) {
unpack0<pe_header_t, LE32>(fo, ih, oh, 1U << 31, set_oft);
}
int PeFile32::canUnpack() {
tribool PeFile32::canUnpack() {
if (!canPack()) // this calls readFileHeader() and readPeHeader()
return false;
return canUnpack0(getFormat() == UPX_F_WINCE_ARM ? 4 : 3, ih.objects, ih.entry, sizeof(ih));
@ -3065,7 +3065,7 @@ void PeFile64::pack0(OutputFile *fo, unsigned subsystem_mask, upx_uint64_t defau
void PeFile64::unpack(OutputFile *fo) { unpack0<pe_header_t, LE64>(fo, ih, oh, 1ULL << 63, false); }
int PeFile64::canUnpack() {
tribool PeFile64::canUnpack() {
if (!canPack()) // this calls readFileHeader() and readPeHeader()
return false;
return canUnpack0(3, ih.objects, ih.entry, sizeof(ih));

View File

@ -503,7 +503,7 @@ protected:
void pack0(OutputFile *fo, unsigned subsystem_mask, upx_uint64_t default_imagebase,
bool last_section_rsrc_only);
virtual void unpack(OutputFile *fo) override;
virtual int canUnpack() override;
virtual tribool canUnpack() override;
virtual void readPeHeader() override;
@ -564,7 +564,7 @@ protected:
void pack0(OutputFile *fo, unsigned subsystem_mask, upx_uint64_t default_imagebase);
virtual void unpack(OutputFile *fo) override;
virtual int canUnpack() override;
virtual tribool canUnpack() override;
virtual void readPeHeader() override;

View File

@ -787,4 +787,60 @@ TEST_CASE("get_ratio") {
CHECK(get_ratio(2 * UPX_RSIZE_MAX, 1024ull * UPX_RSIZE_MAX) == 9999999);
}
template <class T>
struct TestTriBool {
static void test(bool expect_true, int x) noexcept {
CHECK(T(false) == T::False);
CHECK(T(true) == T::True);
CHECK(T(T::Other) == T::Other);
T a;
CHECK(!a);
CHECK(a.isStrictFalse());
CHECK(!a.isStrictTrue());
CHECK(a.isStrictBool());
CHECK(!a.isOther());
a = false;
CHECK(!a);
CHECK(a.isStrictFalse());
CHECK(!a.isStrictTrue());
CHECK(a.isStrictBool());
CHECK(!a.isOther());
a = true;
CHECK(a);
CHECK(!a.isStrictFalse());
CHECK(a.isStrictTrue());
CHECK(a.isStrictBool());
CHECK(!a.isOther());
a = T::Other;
if (expect_true)
CHECK(a);
else
CHECK(!a);
CHECK(!a.isStrictFalse());
CHECK(!a.isStrictTrue());
CHECK(!a.isStrictBool());
CHECK(a.isOther());
a = x;
if (expect_true)
CHECK(a);
else
CHECK(!a);
CHECK(!a.isStrictFalse());
CHECK(!a.isStrictTrue());
CHECK(!a.isStrictBool());
CHECK(a.isOther());
}
};
TEST_CASE("TriBool") {
TestTriBool<tribool>::test(false, -1);
TestTriBool<TriBool<upx_int8_t> >::test(false, -1);
TestTriBool<TriBool<upx_int64_t> >::test(false, -1);
//
TestTriBool<TriBool<upx_int8_t, 2> >::test(true, 2);
TestTriBool<TriBool<upx_uint8_t, 2> >::test(true, 2);
TestTriBool<TriBool<upx_int64_t, 2> >::test(true, 2);
TestTriBool<TriBool<upx_uint64_t, 2> >::test(true, 2);
}
/* vim:set ts=4 sw=4 et: */

View File

@ -194,6 +194,49 @@ inline void owner_delete(T (&array)[]) noexcept DELETED_FUNCTION;
template <class T, size_t N>
inline void owner_delete(T (&array)[N]) noexcept DELETED_FUNCTION;
/*************************************************************************
// TriBool - tri-state bool
**************************************************************************/
template <class T = int, T TOther = -1> // an enum with an underlying type and 3 values
class TriBool {
public:
// types
typedef T underlying_type;
static_assert(std::is_integral_v<underlying_type>);
typedef decltype(T(0) + T(0)) promoted_type;
static_assert(std::is_integral_v<promoted_type>);
static_assert(TOther != 0 && TOther != 1);
enum value_type : underlying_type { False = 0, True = 1, Other = TOther };
// constructors
forceinline TriBool() noexcept = default;
forceinline ~TriBool() noexcept = default;
constexpr TriBool(value_type x) noexcept : value(x) {}
constexpr TriBool(promoted_type x) noexcept : value(x == 0 ? False : (x == 1 ? True : Other)) {}
// access
value_type getValue() const noexcept { return value; }
// checks for > 0, so TOther determines if Other is false (the default) or true
explicit operator bool() const noexcept { return value > False; }
// query; this is NOT the same as operator bool()
bool isStrictFalse() const noexcept { return value == False; }
bool isStrictTrue() const noexcept { return value == True; }
bool isStrictBool() const noexcept { return value == False || value == True; }
bool isOther() const noexcept { return value != False && value != True; }
// "other" can mean many things, depending on usage context, so provide some alternative names:
// forceinline bool isDefault() const noexcept { return isOther(); } // might be misleading
forceinline bool isIndeterminate() const noexcept { return isOther(); }
forceinline bool isUndecided() const noexcept { return isOther(); }
// forceinline bool isUnset() const noexcept { return isOther(); } // might be misleading
constexpr bool operator==(TriBool other) const noexcept { return value == other.value; }
constexpr bool operator==(value_type other) const noexcept { return value == other; }
constexpr bool operator==(promoted_type other) const noexcept { return value == other; }
protected:
// value
value_type value = False;
};
typedef TriBool<> tribool;
/*************************************************************************
// misc. support functions
**************************************************************************/