1
0
mirror of https://github.com/upx/upx synced 2025-09-28 19:06:07 +08:00

Packer::canUnpack() now can return -1.

committer: mfx <mfx> 962126554 +0000
This commit is contained in:
Markus F.X.J. Oberhumer 2000-06-27 17:22:34 +00:00
parent 87a1b66847
commit 51c6566092
24 changed files with 109 additions and 56 deletions

View File

@ -63,6 +63,13 @@ void throwAlreadyPacked(const char *msg)
throw AlreadyPackedException(msg);
}
void throwAlreadyPackedByUPX(const char *msg)
{
if (msg == NULL)
msg = "already packed by UPX";
throwAlreadyPacked(msg);
}
/*************************************************************************
// decompression
@ -109,7 +116,15 @@ void throwBadLoader()
void throwIOException(const char *msg, int e)
{
throw IOException(msg,e);
throw IOException(msg, e);
}
void throwEOFException(const char *msg, int e)
{
if (msg == NULL && e == 0)
msg = "premature end of file";
throw EOFException(msg, e);
}
@ -119,9 +134,9 @@ void throwIOException(const char *msg, int e)
const char *prettyName(const char *n)
{
while (*n >= '0' && *n <= '9') // gcc / egcs
while (*n >= '0' && *n <= '9') // gcc / egcs
n++;
if (strlen(n) > 6 && memcmp(n, "class ", 6) == 0) // Visual C++
if (strncmp(n, "class ", 6) == 0) // Visual C++
n += 6;
return n;
}

View File

@ -192,8 +192,9 @@ public:
// util
**************************************************************************/
#undef NORET
#if 0 && defined(__GNUC__)
// (noreturn) is probably not the correct semantics
// (noreturn) is probably not the correct semantics for throwing exceptions
#define NORET __attribute__((noreturn))
#else
#define NORET
@ -203,6 +204,7 @@ void throwCantPack(const char *msg) NORET;
void throwUnknownExecutableFormat(const char *msg = 0, bool warn = false) NORET;
void throwNotCompressible(const char *msg = 0) NORET;
void throwAlreadyPacked(const char *msg = 0) NORET;
void throwAlreadyPackedByUPX(const char *msg = 0) NORET;
void throwCantUnpack(const char *msg) NORET;
void throwNotPacked(const char *msg = 0) NORET;
void throwFilterException() NORET;
@ -211,6 +213,7 @@ void throwChecksumError() NORET;
void throwCompressedDataViolation() NORET;
void throwInternalError(const char *msg) NORET;
void throwIOException(const char *msg = 0, int e = 0) NORET;
void throwEOFException(const char *msg = 0, int e = 0) NORET;
#undef NORET

View File

@ -137,7 +137,7 @@ int FileBase::readx(void *buf, int len)
{
int l = this->read(buf,len);
if (l != len)
throw EOFException();
throwEOFException();
return l;
}

View File

@ -220,7 +220,7 @@ void PackCom::pack(OutputFile *fo)
//
**************************************************************************/
bool PackCom::canUnpack()
int PackCom::canUnpack()
{
if (!readPackHeader(128, 0))
return false;

View File

@ -48,7 +48,7 @@ public:
virtual void unpack(OutputFile *fo);
virtual bool canPack();
virtual bool canUnpack();
virtual int canUnpack();
protected:
virtual const unsigned getCallTrickOffset() const { return 0x100; }

View File

@ -368,13 +368,13 @@ void PackDjgpp2::pack(OutputFile *fo)
//
**************************************************************************/
bool PackDjgpp2::canUnpack()
int PackDjgpp2::canUnpack()
{
if (!readFileHeader())
return false;
if (is_dlm(fi,coff_offset))
throwCantUnpack("can't handle DLM");
return readPackHeader(1024, coff_offset);
return readPackHeader(1024, coff_offset) ? 1 : -1;
}

View File

@ -49,7 +49,7 @@ public:
virtual void unpack(OutputFile *fo);
virtual bool canPack();
virtual bool canUnpack();
virtual int canUnpack();
protected:
virtual int buildLoader(const Filter *ft);

View File

@ -71,7 +71,7 @@ const int *PackExe::getFilters() const
//
**************************************************************************/
bool PackExe::readExeHeader()
bool PackExe::readFileHeader()
{
ih_exesize = ih_imagesize = ih_overlay = 0;
fi->readx(&ih,sizeof(ih));
@ -95,7 +95,7 @@ bool PackExe::canPack()
{
if (fn_has_ext(fi->getName(),"sys"))
return false;
if (!readExeHeader())
if (!readFileHeader())
return false;
if (file_size < 1024)
throwCantPack("file is too small");
@ -519,9 +519,9 @@ void PackExe::pack(OutputFile *fo)
//
**************************************************************************/
bool PackExe::canUnpack()
int PackExe::canUnpack()
{
if (!readExeHeader())
if (!readFileHeader())
return false;
const off_t off = ih.headsize16*16;
bool b = readPackHeader(128, off);

View File

@ -48,7 +48,7 @@ public:
virtual void unpack(OutputFile *fo);
virtual bool canPack();
virtual bool canUnpack();
virtual int canUnpack();
// unpacker capabilities
virtual bool canUnpackVersion(int version) const
@ -62,7 +62,7 @@ public:
}
protected:
virtual bool readExeHeader(void);
virtual bool readFileHeader(void);
struct exe_header_t
{

View File

@ -343,7 +343,7 @@ void PackLinuxI386elf::pack(OutputFile *fo)
}
if ((off_t)total_in != file_size)
throw EOFException();
throwEOFException();
// write block end marker (uncompressed size 0)
fo->write("\x00\x00\x00\x00", 4);
@ -492,7 +492,7 @@ void PackLinuxI386elf::unpack(OutputFile *fo)
// all bytes must be written
if (total_out != orig_file_size)
throw EOFException();
throwEOFException();
// finally test the checksums
if (ph.c_adler != c_adler || ph.u_adler != u_adler)

View File

@ -46,11 +46,11 @@ public:
virtual const char *getName() const { return "linux/elf386"; }
virtual const int *getFilters() const { return NULL; }
virtual bool canPack();
virtual bool canUnpackFormat(int format) const;
virtual void pack(OutputFile *fo);
virtual void unpack(OutputFile *fo);
virtual bool canPack();
virtual bool canUnpackFormat(int format) const;
virtual bool canUnpackVersion(int version) const
{ return (version >= 11); }

View File

@ -264,11 +264,11 @@ void PackTmt::pack(OutputFile *fo)
}
bool PackTmt::canUnpack()
int PackTmt::canUnpack()
{
if (!PackTmt::readFileHeader())
return false;
return readPackHeader(512,adam_offset);
return readPackHeader(512,adam_offset) ? 1 : -1;
}

View File

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

View File

@ -126,7 +126,7 @@ int PackTos::getLoaderSize() const
// util
**************************************************************************/
bool PackTos::readExeHeader()
bool PackTos::readFileHeader()
{
fi->seek(0,SEEK_SET);
fi->readx(&ih, FH_SIZE);
@ -138,7 +138,7 @@ bool PackTos::readExeHeader()
}
bool PackTos::checkExeHeader()
bool PackTos::checkFileHeader()
{
const unsigned f = ih.fh_flag;
//printf("flags: 0x%x, text: %d, data: %d, bss: %d, sym: %d\n", f, (int)ih.fh_text, (int)ih.fh_data, (int)ih.fh_bss, (int)ih.fh_sym);
@ -235,7 +235,7 @@ static int check_relocs(const upx_byte *relocs, unsigned rsize, unsigned isize,
bool PackTos::canPack()
{
if (!readExeHeader())
if (!readFileHeader())
return false;
unsigned char buf[512];
@ -243,7 +243,7 @@ bool PackTos::canPack()
if (find_le32(buf,sizeof(buf),UPX_MAGIC_LE32))
throwAlreadyPacked();
if (!checkExeHeader())
if (!checkFileHeader())
throwCantPack("unsupported header flags");
if (file_size < 256)
throwCantPack("program too small");
@ -253,7 +253,7 @@ bool PackTos::canPack()
void PackTos::fileInfo()
{
if (!readExeHeader())
if (!readFileHeader())
return;
con_fprintf(stdout, " text: %d, data: %d, sym: %d, bss: %d, flags=0x%x\n",
(int)ih.fh_text, (int)ih.fh_data, (int)ih.fh_sym, (int)ih.fh_bss, (int)ih.fh_flag);
@ -490,17 +490,17 @@ void PackTos::pack(OutputFile *fo)
//
**************************************************************************/
bool PackTos::canUnpack()
int PackTos::canUnpack()
{
if (!readPackHeader(512, 0))
if (!readFileHeader())
return false;
if (!readExeHeader())
if (!readPackHeader(512, 0))
return false;
// check header as set by packer
if ((ih.fh_text & 3) != 0 || (ih.fh_data & 3) != 0 || (ih.fh_bss & 3) != 0
|| ih.fh_sym != 0 || ih.fh_reserved != 0 || ih.fh_reloc > 1)
throwCantUnpack("file damaged");
if (!checkExeHeader())
if (!checkFileHeader())
throwCantUnpack("unsupported header flags");
return true;
}

View File

@ -48,7 +48,7 @@ public:
virtual void unpack(OutputFile *fo);
virtual bool canPack();
virtual bool canUnpack();
virtual int canUnpack();
virtual void fileInfo();
@ -56,8 +56,8 @@ protected:
virtual const upx_byte *getLoader() const;
virtual int getLoaderSize() const;
bool readExeHeader();
bool checkExeHeader();
bool readFileHeader();
bool checkFileHeader();
struct tos_header_t
{

View File

@ -172,7 +172,7 @@ void PackUnix::pack(OutputFile *fo)
total_out += ph.c_len;
}
if ((off_t)total_in != file_size)
throw EOFException();
throwEOFException();
// write block end marker (uncompressed size 0)
fo->write("\x00\x00\x00\x00", 4);
@ -203,7 +203,7 @@ void PackUnix::pack(OutputFile *fo)
// Generic Unix canUnpack().
**************************************************************************/
bool PackUnix::canUnpack()
int PackUnix::canUnpack()
{
upx_byte buf[128];
const int bufsize = sizeof(buf);
@ -310,7 +310,7 @@ void PackUnix::unpack(OutputFile *fo)
// all bytes must be written
if (ph.version > 8 && total_out != orig_file_size)
throw EOFException();
throwEOFException();
// finally test the checksums
if (ph.c_adler != c_adler || ph.u_adler != u_adler)

View File

@ -47,7 +47,7 @@ public:
virtual void unpack(OutputFile *fo);
virtual bool canPack();
virtual bool canUnpack();
virtual int canUnpack();
protected:
// called by the generic pack()
@ -175,7 +175,7 @@ public:
virtual void unpack(OutputFile *fo);
virtual bool canPack();
virtual bool canUnpack();
virtual int canUnpack();
protected:
// virtual const upx_byte *getLoader() const;

View File

@ -137,7 +137,7 @@ void PackBvmlinuxI386::pack(OutputFile *fo)
//
**************************************************************************/
bool PackBvmlinuxI386::canUnpack()
int PackBvmlinuxI386::canUnpack()
{
return false;
}

View File

@ -56,15 +56,15 @@ public:
virtual void unpack(OutputFile *fo);
virtual bool canPack();
virtual bool canUnpack();
virtual int canUnpack();
// unpacker capabilities
virtual bool canUnpackVersion(int version) const
{
return (version == 12);
}
{ return (version == 12); }
protected:
virtual bool testUnpackVersion(int version) const;
unsigned pe_offset;
bool isrtm;
bool readFileHeader();

View File

@ -740,12 +740,12 @@ void PackWcle::decodeEntryTable()
}
bool PackWcle::canUnpack()
int PackWcle::canUnpack()
{
if (!LeFile::readFileHeader())
return false;
// FIXME: 1024 could be too large for some files
return super::readPackHeader(1024, ih.data_pages_offset+exe_offset);
return readPackHeader(1024, ih.data_pages_offset+exe_offset) ? 1 : -1;
}

View File

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

View File

@ -39,7 +39,7 @@
**************************************************************************/
Packer::Packer(InputFile *f) :
fi(f), file_size(-1),
fi(f), file_size(-1), ph_format(-1), ph_version(-1),
uip(NULL), pass(0), total_passes(0), linker(NULL),
last_patch(NULL), last_patch_offset(0)
{
@ -119,6 +119,24 @@ void Packer::fileInfo()
}
bool Packer::testUnpackVersion(int version) const
{
if (version != ph_version && ph_version != -1)
throwCantUnpack("program has been modified; run a virus checker!");
if (!canUnpackVersion(version))
throwCantUnpack("I am not compatible with older versions of UPX");
return true;
}
bool Packer::testUnpackFormat(int format) const
{
if (format != ph_format && ph_format != -1)
throwCantUnpack("program has been modified; run a virus checker!");
return canUnpackFormat(format);
}
/*************************************************************************
// compress
**************************************************************************/
@ -575,8 +593,8 @@ bool Packer::readPackHeader(unsigned len, off_t seek_offset, upx_byte *buf)
// Some formats might be able to unpack old versions because
// their implementation hasn't changed. Ask them.
if (opt->cmd != CMD_FILEINFO)
if (!canUnpackVersion(ph.version))
throwCantUnpack("I am not compatible with older versions of UPX");
if (!testUnpackVersion(ph.version))
return false;
if (ph.c_len >= ph.u_len || (off_t)ph.c_len >= file_size
|| ph.version <= 0 || ph.version >= 0xff)
@ -596,7 +614,7 @@ bool Packer::readPackHeader(unsigned len, off_t seek_offset, upx_byte *buf)
throwCantUnpack("unknown compression method");
// Some formats might be able to unpack "subformats". Ask them.
if (!canUnpackFormat(ph.format))
if (!testUnpackFormat(ph.format))
return false;
return true;

View File

@ -119,6 +119,11 @@ public:
virtual bool canUnpackFormat(int format) const
{ return (format == getFormat()); }
protected:
// unpacker tests - these may throw exceptions
virtual bool testUnpackVersion(int version) const;
virtual bool testUnpackFormat(int format) const;
protected:
virtual void pack(OutputFile *fo) = 0;
virtual void unpack(OutputFile *fo) = 0;
@ -127,10 +132,14 @@ protected:
virtual void fileInfo();
public:
// canPack() should throw a cantPackException eplaining why it
// cannot pack a recognized format.
// canUnpack() can return -1 meaning "format recognized, but file
// is definitely not packed" (see packmast.cpp).
virtual bool canPack() = 0;
virtual bool canUnpack() = 0;
virtual bool canTest() { return canUnpack(); }
virtual bool canList() { return canUnpack(); }
virtual int canUnpack() = 0;
virtual int canTest() { return canUnpack(); }
virtual int canList() { return canUnpack(); }
protected:
// main compression drivers
@ -215,6 +224,8 @@ protected:
InputFile *fi;
off_t file_size; // will get set by constructor
PackHeader ph; // must be filled by canUnpack()
int ph_format;
int ph_version;
// compression buffers
MemBuffer ibuf; // input

View File

@ -112,11 +112,17 @@ static Packer* try_unpack(Packer *p, InputFile *f)
try {
p->initPackHeader();
f->seek(0,SEEK_SET);
if (p->canUnpack())
int r = p->canUnpack();
if (r > 0)
{
f->seek(0,SEEK_SET);
return p;
}
if (r < 0)
{
// FIXME - could stop testing all other unpackers at this time
// see canUnpack() in packer.h
}
} catch (IOException&) {
} catch (...) {
delete p;