Implemented Packer::verifyOverlappingDecompression().
committer: mfx <mfx> 978465508 +0000
This commit is contained in:
parent
d328e834b1
commit
572082ac2b
2
TODO
2
TODO
@ -77,6 +77,8 @@ FORMAT WATCOM/LE
|
||||
|
||||
- implement compressWithFilters()
|
||||
|
||||
- add a call to verifyOverlappingDecompression()
|
||||
|
||||
|
||||
FORMAT WIN32/PE
|
||||
===============
|
||||
|
||||
10
src/mem.cpp
10
src/mem.cpp
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -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);
|
||||
|
||||
|
||||
@ -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))
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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))
|
||||
|
||||
@ -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);
|
||||
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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
|
||||
|
||||
Loading…
Reference in New Issue
Block a user