Implemented Packer::verifyOverlappingDecompression().

committer: mfx <mfx> 978465508 +0000
This commit is contained in:
Markus F.X.J. Oberhumer 2001-01-02 19:58:28 +00:00
parent d328e834b1
commit 572082ac2b
14 changed files with 58 additions and 58 deletions

2
TODO
View File

@ -77,6 +77,8 @@ FORMAT WATCOM/LE
- implement compressWithFilters()
- add a call to verifyOverlappingDecompression()
FORMAT WIN32/PE
===============

View File

@ -96,15 +96,7 @@ void MemBuffer::alloc(unsigned size)
void MemBuffer::allocForCompression(unsigned uncompressed_size)
{
// Idea:
// We allocate the buffer at an offset of 4096 so
// that we could do an in-place decompression for
// verifying our overlap_overhead at the end
// of packing.
//
// See Packer::verifyOverlappingDecompression().
alloc(uncompressed_size + uncompressed_size/8 + 256, MAX_OVERLAP_OVERHEAD);
alloc(uncompressed_size + uncompressed_size/8 + 256, 0);
}

View File

@ -52,8 +52,6 @@ public:
operator unsigned char * () { return ptr; }
//operator const unsigned char * () const { return ptr; }
enum { MAX_OVERLAP_OVERHEAD = 4096 };
private:
void alloc(unsigned size, unsigned base_offset);

View File

@ -209,7 +209,7 @@ void PackCom::pack(OutputFile *fo)
patchLoader(fo, loader, lsize, calls);
// verify
verifyOverlappingDecompression(&obuf, ph.overlap_overhead);
verifyOverlappingDecompression();
// finally check the compression ratio
if (!checkFinalCompressionRatio(fo))

View File

@ -339,7 +339,7 @@ void PackDjgpp2::pack(OutputFile *fo)
#endif
// verify
verifyOverlappingDecompression(&obuf, ph.overlap_overhead);
verifyOverlappingDecompression();
// handle overlay
// FIXME: only Allegro pakfiles are supported

View File

@ -536,7 +536,7 @@ void PackExe::pack(OutputFile *fo)
#endif
// verify
verifyOverlappingDecompression(&obuf, ph.overlap_overhead);
verifyOverlappingDecompression();
// copy the overlay
copyOverlay(fo, ih_overlay, &obuf);

View File

@ -217,11 +217,13 @@ void PackLinuxI386elf::packExtent(
// compress
ph.u_len = l;
compress(ibuf, obuf); // ignore return value
ph.overlap_overhead = 0;
(void) compress(ibuf, obuf); // ignore return value
if (ph.c_len < ph.u_len)
{
if (!testOverlappingDecompression(obuf, OVERHEAD))
ph.overlap_overhead = OVERHEAD;
if (!testOverlappingDecompression(obuf, ph.overlap_overhead))
throwNotCompressible();
}
else
@ -241,7 +243,7 @@ void PackLinuxI386elf::packExtent(
if (ph.c_len < ph.u_len)
{
fo->write(obuf, ph.c_len);
verifyOverlappingDecompression(&obuf, OVERHEAD);
verifyOverlappingDecompression();
}
else
fo->write(ibuf, ph.u_len);

View File

@ -274,7 +274,7 @@ void PackTmt::pack(OutputFile *fo)
fo->write(rel_entry,sizeof (rel_entry));
// verify
verifyOverlappingDecompression(&obuf, ph.overlap_overhead);
verifyOverlappingDecompression();
// copy the overlay
copyOverlay(fo, overlay, &obuf);

View File

@ -545,7 +545,7 @@ void PackTos::pack(OutputFile *fo)
fo->write("\x00\x00\x00\x00",4);
// verify
verifyOverlappingDecompression(&obuf, ph.overlap_overhead);
verifyOverlappingDecompression();
// copy the overlay
copyOverlay(fo, overlay, &obuf);

View File

@ -140,11 +140,13 @@ void PackUnix::pack(OutputFile *fo)
// compress
ph.u_len = l;
(void) compress(ibuf, obuf); // ignore return value
ph.overlap_overhead = 0;
(void) compress(ibuf, obuf); // ignore return value
if (ph.c_len < ph.u_len)
{
if (!testOverlappingDecompression(obuf, OVERHEAD))
ph.overlap_overhead = OVERHEAD;
if (!testOverlappingDecompression(obuf, ph.overlap_overhead))
throwNotCompressible();
}
else
@ -165,7 +167,7 @@ void PackUnix::pack(OutputFile *fo)
if (ph.c_len < ph.u_len)
{
fo->write(obuf, ph.c_len);
verifyOverlappingDecompression(&obuf, OVERHEAD);
verifyOverlappingDecompression();
}
else
fo->write(ibuf, ph.u_len);

View File

@ -342,7 +342,7 @@ void PackBvmlinuzI386::pack(OutputFile *fo)
#endif
// verify
verifyOverlappingDecompression(&obuf, ph.overlap_overhead);
verifyOverlappingDecompression();
// finally check the compression ratio
if (!checkFinalCompressionRatio(fo))

View File

@ -1873,6 +1873,9 @@ void PackW32Pe::pack(OutputFile *fo)
printf("%-13s: relocs : %8ld bytes\n", getName(), (long) soxrelocs);
#endif
// verify
verifyOverlappingDecompression();
// copy the overlay
copyOverlay(fo, overlay, &obuf);

View File

@ -47,7 +47,7 @@ Packer::Packer(InputFile *f) :
{
file_size = f->st.st_size;
uip = new UiPacker(this);
memset(&ph,0,sizeof(ph));
memset(&ph, 0, sizeof(ph));
}
@ -151,12 +151,11 @@ bool Packer::compress(upx_bytep in, upx_bytep out,
return false;
#else
ph.c_len = 0;
assert(ph.level >= 1); assert(ph.level <= 10);
const int level = ph.level;
assert(level >= 1); assert(level <= 10);
ph.saved_u_adler = ph.u_adler;
ph.saved_c_adler = ph.c_adler;
// update checksum of uncompressed data
const unsigned saved_u_adler = ph.u_adler;
ph.u_adler = upx_adler32(ph.u_adler,in,ph.u_len);
// set compression paramters
@ -173,7 +172,7 @@ bool Packer::compress(upx_bytep in, upx_bytep out,
#if 0
else
// this is based on experimentation
conf.c_flags = (level >= 7) ? 0 : 1 | 2;
conf.c_flags = (ph.level >= 7) ? 0 : 1 | 2;
#endif
if (opt->crp.p_level != -1)
conf.p_level = opt->crp.p_level;
@ -187,7 +186,7 @@ bool Packer::compress(upx_bytep in, upx_bytep out,
// Avoid too many progress bar updates. 64 is s->bar_len in ui.cpp.
unsigned step = (ph.u_len < 64*1024) ? 0 : ph.u_len / 64;
#if defined(WITH_NRV)
if ((level >= 7) || (level >= 4 && ph.u_len >= 512*1024))
if (ph.level >= 7 || (ph.level >= 4 && ph.u_len >= 512*1024))
step = 0;
#endif
if (ui_pass >= 0)
@ -202,7 +201,7 @@ bool Packer::compress(upx_bytep in, upx_bytep out,
memset(result, 0, sizeof(result));
int r = upx_compress(in, ph.u_len, out, &ph.c_len,
uip->getCallback(),
ph.method, level, &conf, result);
ph.method, ph.level, &conf, result);
if (r == UPX_E_OUT_OF_MEMORY)
throwCantPack("out of memory");
if (r != UPX_E_OK)
@ -232,7 +231,7 @@ bool Packer::compress(upx_bytep in, upx_bytep out,
// update checksum of compressed data
ph.c_adler = upx_adler32(ph.c_adler,out,ph.c_len);
// Decompress and verify. Skip this when using the fastest level.
if (level > 1)
if (ph.level > 1)
{
// decompress
unsigned new_len = ph.u_len;
@ -244,7 +243,7 @@ bool Packer::compress(upx_bytep in, upx_bytep out,
throwInternalError("decompression failed (size error)");
// verify decompression
if (ph.u_adler != upx_adler32(saved_u_adler,in,ph.u_len))
if (ph.u_adler != upx_adler32(ph.saved_u_adler,in,ph.u_len))
throwInternalError("decompression failed (checksum error)");
}
return true;
@ -257,9 +256,6 @@ bool Packer::checkCompressionRatio(unsigned u_len, unsigned c_len) const
assert((int)u_len > 0);
assert((int)c_len > 0);
// this assertion may fail if we compress the BSS segment -- disabled
//assert((off_t)u_len < file_size);
#if 1
if (c_len + 512 >= u_len) // min. 512 bytes gain
return false;
@ -305,23 +301,21 @@ void Packer::decompress(const upx_bytep in, upx_bytep out,
// verify checksum of compressed data
if (verify_checksum)
{
adler = upx_adler32(0,NULL,0);
adler = upx_adler32(adler,in,ph.c_len);
adler = upx_adler32(ph.saved_c_adler, in, ph.c_len);
if (adler != ph.c_adler)
throwChecksumError();
}
// decompress
unsigned new_len = ph.u_len;
int r = upx_decompress(in,ph.c_len,out,&new_len,ph.method);
int r = upx_decompress(in, ph.c_len, out, &new_len, ph.method);
if (r != UPX_E_OK || new_len != ph.u_len)
throwCompressedDataViolation();
// verify checksum of decompressed data
if (verify_checksum)
{
adler = upx_adler32(0,NULL,0);
adler = upx_adler32(adler,out,ph.u_len);
adler = upx_adler32(ph.saved_u_adler, out, ph.u_len);
if (adler != ph.u_adler)
throwChecksumError();
}
@ -360,18 +354,16 @@ bool Packer::testOverlappingDecompression(const upx_bytep buf,
}
void Packer::verifyOverlappingDecompression(MemBuffer *buf,
unsigned overlap_overhead)
void Packer::verifyOverlappingDecompression()
{
#if defined(UNUPX)
#else
// FIXME (well, this is complete paranoia anyway)
//
assert(ph.c_len < ph.u_len);
assert((int)ph.overlap_overhead > 0);
#if 1 && !defined(UNUPX)
// Idea:
// buf was allocated with MemBuffer.allocForCompression(), and
// obuf was allocated with MemBuffer::allocForCompression(), and
// its contents are no longer needed, i.e. the compressed data
// must have been already written.
// We now could perform a real overlapping decompression and
// We now can perform a real overlapping decompression and
// verify the checksum.
//
// Note:
@ -381,9 +373,15 @@ void Packer::verifyOverlappingDecompression(MemBuffer *buf,
//
// See also:
// Filter::verifyUnfilter()
#endif
UNUSED(buf);
UNUSED(overlap_overhead);
if (ph.level == 1)
return;
unsigned offset = (ph.u_len + ph.overlap_overhead) - ph.c_len;
if (offset + ph.c_len > obuf.getSize())
return;
memmove(obuf + offset, obuf, ph.c_len);
decompress(obuf + offset, obuf, true);
#endif /* !UNUPX */
}
@ -473,7 +471,7 @@ void Packer::handleStub(InputFile *fif, OutputFile *fo, long size)
void Packer::checkOverlay(unsigned overlay)
{
assert((int)overlay >= 0);
assert((off_t)overlay >= 0);
assert((off_t)overlay < file_size);
if (overlay == 0)
return;
@ -566,7 +564,7 @@ void Packer::initPackHeader()
ph.format = getFormat();
ph.method = -1;
ph.level = -1;
ph.c_adler = ph.u_adler = upx_adler32(0,NULL,0);
ph.u_adler = ph.c_adler = ph.saved_u_adler = ph.saved_c_adler = upx_adler32(0,NULL,0);
ph.buf_offset = -1;
ph.u_file_size = file_size;
}
@ -1255,8 +1253,8 @@ void Packer::compressWithFilters(Filter *parm_ft,
}
#if 0
printf("\n%2d %02x: %d + %d = %d (best: %d + %d = %d)\n", ph.method, ph.filter,
ph.c_len, getLoaderSize(), ph.c_len + getLoaderSize(),
best_ph.c_len, best_ph_lsize, best_ph.c_len + best_ph_lsize);
ph.c_len, getLoaderSize(), ph.c_len + getLoaderSize(),
best_ph.c_len, best_ph_lsize, best_ph.c_len + best_ph_lsize);
#endif
bool update = false;
if (ph.c_len + lsize < best_ph.c_len + best_ph_lsize)

View File

@ -75,6 +75,10 @@ public:
int filter_cto;
int header_checksum;
//
unsigned saved_u_adler;
unsigned saved_c_adler;
// info fields set by fillPackHeader()
long buf_offset;
@ -178,8 +182,7 @@ protected:
unsigned range = 0,
unsigned upper_limit = ~0u) const;
// destructive decompress + verify
virtual void verifyOverlappingDecompression(MemBuffer *buf,
unsigned overlap_overhead);
virtual void verifyOverlappingDecompression();
// packheader handling