diff --git a/src/conf.h b/src/conf.h index 094e57df..3e240d5b 100644 --- a/src/conf.h +++ b/src/conf.h @@ -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" diff --git a/src/help.cpp b/src/help.cpp index 9ccb6ce4..c48c069a 100644 --- a/src/help.cpp +++ b/src/help.cpp @@ -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; diff --git a/src/main.cpp b/src/main.cpp index 0dd4ec58..72d6ce46 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -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: diff --git a/src/options.h b/src/options.h index 35030722..cce2894e 100644 --- a/src/options.h +++ b/src/options.h @@ -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 compress_resources; + TriBool compress_rt[25]; // 25 == RT_LAST int strip_relocs; const char *keep_resource; } win32_pe; diff --git a/src/p_com.cpp b/src/p_com.cpp index fbb558d5..75b166fd 100644 --- a/src/p_com.cpp +++ b/src/p_com.cpp @@ -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) diff --git a/src/p_com.h b/src/p_com.h index b43f7f60..3f0660de 100644 --- a/src/p_com.h +++ b/src/p_com.h @@ -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; diff --git a/src/p_djgpp2.cpp b/src/p_djgpp2.cpp index a371fc48..af0d6f24 100644 --- a/src/p_djgpp2.cpp +++ b/src/p_djgpp2.cpp @@ -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)) diff --git a/src/p_djgpp2.h b/src/p_djgpp2.h index 7744abfe..5aaf98bf 100644 --- a/src/p_djgpp2.h +++ b/src/p_djgpp2.h @@ -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); diff --git a/src/p_exe.cpp b/src/p_exe.cpp index d32a1e26..1ad2d752 100644 --- a/src/p_exe.cpp +++ b/src/p_exe.cpp @@ -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; diff --git a/src/p_exe.h b/src/p_exe.h index d4f2f5ac..daee2cad 100644 --- a/src/p_exe.h +++ b/src/p_exe.h @@ -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 { diff --git a/src/p_lx_elf.cpp b/src/p_lx_elf.cpp index 64d379b6..f8a13cb6 100644 --- a/src/p_lx_elf.cpp +++ b/src/p_lx_elf.cpp @@ -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; diff --git a/src/p_lx_elf.h b/src/p_lx_elf.h index 77e85744..d59e401f 100644 --- a/src/p_lx_elf.h +++ b/src/p_lx_elf.h @@ -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 diff --git a/src/p_lx_exc.cpp b/src/p_lx_exc.cpp index 9aea093e..24f83c19 100644 --- a/src/p_lx_exc.cpp +++ b/src/p_lx_exc.cpp @@ -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(); diff --git a/src/p_lx_exc.h b/src/p_lx_exc.h index 6730baf5..484801c8 100644 --- a/src/p_lx_exc.h +++ b/src/p_lx_exc.h @@ -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 diff --git a/src/p_lx_interp.cpp b/src/p_lx_interp.cpp index a354e9a1..bd03d262 100644 --- a/src/p_lx_interp.cpp +++ b/src/p_lx_interp.cpp @@ -64,7 +64,7 @@ PackLinuxElf32x86interp::~PackLinuxElf32x86interp() { } -bool PackLinuxElf32x86interp::canPack() +tribool PackLinuxElf32x86interp::canPack() { if (opt->o_unix.make_ptinterp) { return true; diff --git a/src/p_lx_interp.h b/src/p_lx_interp.h index 2a7e4f91..4c464fee 100644 --- a/src/p_lx_interp.h +++ b/src/p_lx_interp.h @@ -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: diff --git a/src/p_lx_sh.cpp b/src/p_lx_sh.cpp index 3780db4e..82a1850d 100644 --- a/src/p_lx_sh.cpp +++ b/src/p_lx_sh.cpp @@ -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 diff --git a/src/p_lx_sh.h b/src/p_lx_sh.h index 23b30629..541ae8e5 100644 --- a/src/p_lx_sh.h +++ b/src/p_lx_sh.h @@ -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); } diff --git a/src/p_mach.cpp b/src/p_mach.cpp index 205efb96..76f3947f 100644 --- a/src/p_mach.cpp +++ b/src/p_mach.cpp @@ -1615,7 +1615,7 @@ void PackMachBase::unpack(OutputFile *fo) // The prize is the value of overlay_offset: the offset of compressed data template -int PackMachBase::canUnpack() +tribool PackMachBase::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::get_mod_init_func(Mach_segment_command const *segp } template -bool PackMachBase::canPack() +tribool PackMachBase::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]; diff --git a/src/p_mach.h b/src/p_mach.h index 165c5017..899d517f 100644 --- a/src/p_mach.h +++ b/src/p_mach.h @@ -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 diff --git a/src/p_ps1.cpp b/src/p_ps1.cpp index cc4ce216..a269e58d 100644 --- a/src/p_ps1.cpp +++ b/src/p_ps1.cpp @@ -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)) diff --git a/src/p_ps1.h b/src/p_ps1.h index 0724ac07..416364a3 100644 --- a/src/p_ps1.h +++ b/src/p_ps1.h @@ -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); diff --git a/src/p_sys.cpp b/src/p_sys.cpp index 46246cb7..4913d0a3 100644 --- a/src/p_sys.cpp +++ b/src/p_sys.cpp @@ -40,7 +40,7 @@ static const CLANG_FORMAT_DUMMY_STATEMENT // **************************************************************************/ -bool PackSys::canPack() { +tribool PackSys::canPack() { byte buf[128]; fi->readx(buf, sizeof(buf)); diff --git a/src/p_sys.h b/src/p_sys.h index da34a9c9..cd255ead 100644 --- a/src/p_sys.h +++ b/src/p_sys.h @@ -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; } diff --git a/src/p_tmt.cpp b/src/p_tmt.cpp index 051b3c36..a4b3b3db 100644 --- a/src/p_tmt.cpp +++ b/src/p_tmt.cpp @@ -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); diff --git a/src/p_tmt.h b/src/p_tmt.h index 97fd9a6c..b9277920 100644 --- a/src/p_tmt.h +++ b/src/p_tmt.h @@ -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(); diff --git a/src/p_tos.cpp b/src/p_tos.cpp index eaeb30e7..204e0373 100644 --- a/src/p_tos.cpp +++ b/src/p_tos.cpp @@ -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)) diff --git a/src/p_tos.h b/src/p_tos.h index d752d518..11d91c24 100644 --- a/src/p_tos.h +++ b/src/p_tos.h @@ -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; diff --git a/src/p_unix.cpp b/src/p_unix.cpp index 0ad711dd..a9dfbe2d 100644 --- a/src/p_unix.cpp +++ b/src/p_unix.cpp @@ -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. diff --git a/src/p_unix.h b/src/p_unix.h index 0c705249..a492afc8 100644 --- a/src/p_unix.h +++ b/src/p_unix.h @@ -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: diff --git a/src/p_vmlinx.cpp b/src/p_vmlinx.cpp index 7751c7d0..106c82dc 100644 --- a/src/p_vmlinx.cpp +++ b/src/p_vmlinx.cpp @@ -143,7 +143,7 @@ typename T::Shdr const *PackVmlinuxBase::getElfSections() } template -bool PackVmlinuxBase::canPack() +tribool PackVmlinuxBase::canPack() { fi->seek(0, SEEK_SET); fi->readx(&ehdri, sizeof(ehdri)); @@ -553,7 +553,7 @@ void PackVmlinuxBase::pack(OutputFile *fo) } template -int PackVmlinuxBase::canUnpack() +tribool PackVmlinuxBase::canUnpack() { fi->seek(0, SEEK_SET); fi->readx(&ehdri, sizeof(ehdri)); diff --git a/src/p_vmlinx.h b/src/p_vmlinx.h index b3cc90b0..3471f082 100644 --- a/src/p_vmlinx.h +++ b/src/p_vmlinx.h @@ -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, diff --git a/src/p_vmlinz.cpp b/src/p_vmlinz.cpp index 8025a0c5..8e0cbb40 100644 --- a/src/p_vmlinz.cpp +++ b/src/p_vmlinz.cpp @@ -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; diff --git a/src/p_vmlinz.h b/src/p_vmlinz.h index e658d8a5..a19b8819 100644 --- a/src/p_vmlinz.h +++ b/src/p_vmlinz.h @@ -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(); diff --git a/src/p_w32pe_i386.cpp b/src/p_w32pe_i386.cpp index 689fbc89..532301a9 100644 --- a/src/p_w32pe_i386.cpp +++ b/src/p_w32pe_i386.cpp @@ -75,7 +75,7 @@ int PackW32PeI386::readFileHeader() { // pack **************************************************************************/ -bool PackW32PeI386::canPack() { +tribool PackW32PeI386::canPack() { if (!readFileHeader()) return false; checkMachine(ih.cpu); diff --git a/src/p_w32pe_i386.h b/src/p_w32pe_i386.h index 20923691..1bd094eb 100644 --- a/src/p_w32pe_i386.h +++ b/src/p_w32pe_i386.h @@ -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; diff --git a/src/p_w64pe_amd64.cpp b/src/p_w64pe_amd64.cpp index 6ee9f4a9..a9f5f178 100644 --- a/src/p_w64pe_amd64.cpp +++ b/src/p_w64pe_amd64.cpp @@ -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); diff --git a/src/p_w64pe_amd64.h b/src/p_w64pe_amd64.h index ac1e9296..a0a18fff 100644 --- a/src/p_w64pe_amd64.h +++ b/src/p_w64pe_amd64.h @@ -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; diff --git a/src/p_w64pe_arm64.cpp b/src/p_w64pe_arm64.cpp index fa70c2a7..9451bb59 100644 --- a/src/p_w64pe_arm64.cpp +++ b/src/p_w64pe_arm64.cpp @@ -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); diff --git a/src/p_w64pe_arm64.h b/src/p_w64pe_arm64.h index d0c37d18..c8cf4d7d 100644 --- a/src/p_w64pe_arm64.h +++ b/src/p_w64pe_arm64.h @@ -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: */ diff --git a/src/p_wcle.cpp b/src/p_wcle.cpp index 912c738e..ec8e03ac 100644 --- a/src/p_wcle.cpp +++ b/src/p_wcle.cpp @@ -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); diff --git a/src/p_wcle.h b/src/p_wcle.h index f7cb4689..a525efc1 100644 --- a/src/p_wcle.h +++ b/src/p_wcle.h @@ -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); diff --git a/src/p_wince_arm.cpp b/src/p_wince_arm.cpp index 47d93f25..0cbb360e 100644 --- a/src/p_wince_arm.cpp +++ b/src/p_wince_arm.cpp @@ -111,7 +111,7 @@ void PackWinCeArm::processTls(Interval *) // pass 1 // pack **************************************************************************/ -bool PackWinCeArm::canPack() { +tribool PackWinCeArm::canPack() { if (!readFileHeader()) return false; checkMachine(ih.cpu); diff --git a/src/p_wince_arm.h b/src/p_wince_arm.h index 39939cd4..9078efd7 100644 --- a/src/p_wince_arm.h +++ b/src/p_wince_arm.h @@ -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; diff --git a/src/packer.h b/src/packer.h index 3b4461e3..3f9f3de9 100644 --- a/src/packer.h +++ b/src/packer.h @@ -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; diff --git a/src/packmast.cpp b/src/packmast.cpp index 3ea59a55..c303614b 100644 --- a/src/packmast.cpp +++ b/src/packmast.cpp @@ -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 !!! diff --git a/src/packmast.h b/src/packmast.h index ab7709cf..16a61c25 100644 --- a/src/packmast.h +++ b/src/packmast.h @@ -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; diff --git a/src/pefile.cpp b/src/pefile.cpp index 7f5ee917..46cfa8a2 100644 --- a/src/pefile.cpp +++ b/src/pefile.cpp @@ -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(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(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)); diff --git a/src/pefile.h b/src/pefile.h index 5af8efb5..377d0ab4 100644 --- a/src/pefile.h +++ b/src/pefile.h @@ -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; diff --git a/src/util/util.cpp b/src/util/util.cpp index bfa6879e..2843123f 100644 --- a/src/util/util.cpp +++ b/src/util/util.cpp @@ -787,4 +787,60 @@ TEST_CASE("get_ratio") { CHECK(get_ratio(2 * UPX_RSIZE_MAX, 1024ull * UPX_RSIZE_MAX) == 9999999); } +template +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::test(false, -1); + TestTriBool >::test(false, -1); + TestTriBool >::test(false, -1); + // + TestTriBool >::test(true, 2); + TestTriBool >::test(true, 2); + TestTriBool >::test(true, 2); + TestTriBool >::test(true, 2); +} + /* vim:set ts=4 sw=4 et: */ diff --git a/src/util/util.h b/src/util/util.h index 47539100..ab96c04f 100644 --- a/src/util/util.h +++ b/src/util/util.h @@ -194,6 +194,49 @@ inline void owner_delete(T (&array)[]) noexcept DELETED_FUNCTION; template inline void owner_delete(T (&array)[N]) noexcept DELETED_FUNCTION; +/************************************************************************* +// TriBool - tri-state bool +**************************************************************************/ + +template // an enum with an underlying type and 3 values +class TriBool { +public: + // types + typedef T underlying_type; + static_assert(std::is_integral_v); + typedef decltype(T(0) + T(0)) promoted_type; + static_assert(std::is_integral_v); + 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 **************************************************************************/