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
View File
@@ -77,6 +77,8 @@ FORMAT WATCOM/LE
- implement compressWithFilters() - implement compressWithFilters()
- add a call to verifyOverlappingDecompression()
FORMAT WIN32/PE FORMAT WIN32/PE
=============== ===============
+1 -9
View File
@@ -96,15 +96,7 @@ void MemBuffer::alloc(unsigned size)
void MemBuffer::allocForCompression(unsigned uncompressed_size) void MemBuffer::allocForCompression(unsigned uncompressed_size)
{ {
// Idea: alloc(uncompressed_size + uncompressed_size/8 + 256, 0);
// 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);
} }
-2
View File
@@ -52,8 +52,6 @@ public:
operator unsigned char * () { return ptr; } operator unsigned char * () { return ptr; }
//operator const unsigned char * () const { return ptr; } //operator const unsigned char * () const { return ptr; }
enum { MAX_OVERLAP_OVERHEAD = 4096 };
private: private:
void alloc(unsigned size, unsigned base_offset); void alloc(unsigned size, unsigned base_offset);
+1 -1
View File
@@ -209,7 +209,7 @@ void PackCom::pack(OutputFile *fo)
patchLoader(fo, loader, lsize, calls); patchLoader(fo, loader, lsize, calls);
// verify // verify
verifyOverlappingDecompression(&obuf, ph.overlap_overhead); verifyOverlappingDecompression();
// finally check the compression ratio // finally check the compression ratio
if (!checkFinalCompressionRatio(fo)) if (!checkFinalCompressionRatio(fo))
+1 -1
View File
@@ -339,7 +339,7 @@ void PackDjgpp2::pack(OutputFile *fo)
#endif #endif
// verify // verify
verifyOverlappingDecompression(&obuf, ph.overlap_overhead); verifyOverlappingDecompression();
// handle overlay // handle overlay
// FIXME: only Allegro pakfiles are supported // FIXME: only Allegro pakfiles are supported
+1 -1
View File
@@ -536,7 +536,7 @@ void PackExe::pack(OutputFile *fo)
#endif #endif
// verify // verify
verifyOverlappingDecompression(&obuf, ph.overlap_overhead); verifyOverlappingDecompression();
// copy the overlay // copy the overlay
copyOverlay(fo, ih_overlay, &obuf); copyOverlay(fo, ih_overlay, &obuf);
+5 -3
View File
@@ -217,11 +217,13 @@ void PackLinuxI386elf::packExtent(
// compress // compress
ph.u_len = l; 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 (ph.c_len < ph.u_len)
{ {
if (!testOverlappingDecompression(obuf, OVERHEAD)) ph.overlap_overhead = OVERHEAD;
if (!testOverlappingDecompression(obuf, ph.overlap_overhead))
throwNotCompressible(); throwNotCompressible();
} }
else else
@@ -241,7 +243,7 @@ void PackLinuxI386elf::packExtent(
if (ph.c_len < ph.u_len) if (ph.c_len < ph.u_len)
{ {
fo->write(obuf, ph.c_len); fo->write(obuf, ph.c_len);
verifyOverlappingDecompression(&obuf, OVERHEAD); verifyOverlappingDecompression();
} }
else else
fo->write(ibuf, ph.u_len); fo->write(ibuf, ph.u_len);
+1 -1
View File
@@ -274,7 +274,7 @@ void PackTmt::pack(OutputFile *fo)
fo->write(rel_entry,sizeof (rel_entry)); fo->write(rel_entry,sizeof (rel_entry));
// verify // verify
verifyOverlappingDecompression(&obuf, ph.overlap_overhead); verifyOverlappingDecompression();
// copy the overlay // copy the overlay
copyOverlay(fo, overlay, &obuf); copyOverlay(fo, overlay, &obuf);
+1 -1
View File
@@ -545,7 +545,7 @@ void PackTos::pack(OutputFile *fo)
fo->write("\x00\x00\x00\x00",4); fo->write("\x00\x00\x00\x00",4);
// verify // verify
verifyOverlappingDecompression(&obuf, ph.overlap_overhead); verifyOverlappingDecompression();
// copy the overlay // copy the overlay
copyOverlay(fo, overlay, &obuf); copyOverlay(fo, overlay, &obuf);
+4 -2
View File
@@ -140,11 +140,13 @@ void PackUnix::pack(OutputFile *fo)
// compress // compress
ph.u_len = l; ph.u_len = l;
ph.overlap_overhead = 0;
(void) compress(ibuf, obuf); // ignore return value (void) compress(ibuf, obuf); // ignore return value
if (ph.c_len < ph.u_len) if (ph.c_len < ph.u_len)
{ {
if (!testOverlappingDecompression(obuf, OVERHEAD)) ph.overlap_overhead = OVERHEAD;
if (!testOverlappingDecompression(obuf, ph.overlap_overhead))
throwNotCompressible(); throwNotCompressible();
} }
else else
@@ -165,7 +167,7 @@ void PackUnix::pack(OutputFile *fo)
if (ph.c_len < ph.u_len) if (ph.c_len < ph.u_len)
{ {
fo->write(obuf, ph.c_len); fo->write(obuf, ph.c_len);
verifyOverlappingDecompression(&obuf, OVERHEAD); verifyOverlappingDecompression();
} }
else else
fo->write(ibuf, ph.u_len); fo->write(ibuf, ph.u_len);
+1 -1
View File
@@ -342,7 +342,7 @@ void PackBvmlinuzI386::pack(OutputFile *fo)
#endif #endif
// verify // verify
verifyOverlappingDecompression(&obuf, ph.overlap_overhead); verifyOverlappingDecompression();
// finally check the compression ratio // finally check the compression ratio
if (!checkFinalCompressionRatio(fo)) if (!checkFinalCompressionRatio(fo))
+3
View File
@@ -1873,6 +1873,9 @@ void PackW32Pe::pack(OutputFile *fo)
printf("%-13s: relocs : %8ld bytes\n", getName(), (long) soxrelocs); printf("%-13s: relocs : %8ld bytes\n", getName(), (long) soxrelocs);
#endif #endif
// verify
verifyOverlappingDecompression();
// copy the overlay // copy the overlay
copyOverlay(fo, overlay, &obuf); copyOverlay(fo, overlay, &obuf);
+27 -29
View File
@@ -151,12 +151,11 @@ bool Packer::compress(upx_bytep in, upx_bytep out,
return false; return false;
#else #else
ph.c_len = 0; ph.c_len = 0;
assert(ph.level >= 1); assert(ph.level <= 10);
const int level = ph.level; ph.saved_u_adler = ph.u_adler;
assert(level >= 1); assert(level <= 10); ph.saved_c_adler = ph.c_adler;
// update checksum of uncompressed data // 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); ph.u_adler = upx_adler32(ph.u_adler,in,ph.u_len);
// set compression paramters // set compression paramters
@@ -173,7 +172,7 @@ bool Packer::compress(upx_bytep in, upx_bytep out,
#if 0 #if 0
else else
// this is based on experimentation // this is based on experimentation
conf.c_flags = (level >= 7) ? 0 : 1 | 2; conf.c_flags = (ph.level >= 7) ? 0 : 1 | 2;
#endif #endif
if (opt->crp.p_level != -1) if (opt->crp.p_level != -1)
conf.p_level = opt->crp.p_level; 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. // 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; unsigned step = (ph.u_len < 64*1024) ? 0 : ph.u_len / 64;
#if defined(WITH_NRV) #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; step = 0;
#endif #endif
if (ui_pass >= 0) if (ui_pass >= 0)
@@ -202,7 +201,7 @@ bool Packer::compress(upx_bytep in, upx_bytep out,
memset(result, 0, sizeof(result)); memset(result, 0, sizeof(result));
int r = upx_compress(in, ph.u_len, out, &ph.c_len, int r = upx_compress(in, ph.u_len, out, &ph.c_len,
uip->getCallback(), uip->getCallback(),
ph.method, level, &conf, result); ph.method, ph.level, &conf, result);
if (r == UPX_E_OUT_OF_MEMORY) if (r == UPX_E_OUT_OF_MEMORY)
throwCantPack("out of memory"); throwCantPack("out of memory");
if (r != UPX_E_OK) if (r != UPX_E_OK)
@@ -232,7 +231,7 @@ bool Packer::compress(upx_bytep in, upx_bytep out,
// update checksum of compressed data // update checksum of compressed data
ph.c_adler = upx_adler32(ph.c_adler,out,ph.c_len); ph.c_adler = upx_adler32(ph.c_adler,out,ph.c_len);
// Decompress and verify. Skip this when using the fastest level. // Decompress and verify. Skip this when using the fastest level.
if (level > 1) if (ph.level > 1)
{ {
// decompress // decompress
unsigned new_len = ph.u_len; unsigned new_len = ph.u_len;
@@ -244,7 +243,7 @@ bool Packer::compress(upx_bytep in, upx_bytep out,
throwInternalError("decompression failed (size error)"); throwInternalError("decompression failed (size error)");
// verify decompression // 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)"); throwInternalError("decompression failed (checksum error)");
} }
return true; return true;
@@ -257,9 +256,6 @@ bool Packer::checkCompressionRatio(unsigned u_len, unsigned c_len) const
assert((int)u_len > 0); assert((int)u_len > 0);
assert((int)c_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 1
if (c_len + 512 >= u_len) // min. 512 bytes gain if (c_len + 512 >= u_len) // min. 512 bytes gain
return false; return false;
@@ -305,8 +301,7 @@ void Packer::decompress(const upx_bytep in, upx_bytep out,
// verify checksum of compressed data // verify checksum of compressed data
if (verify_checksum) if (verify_checksum)
{ {
adler = upx_adler32(0,NULL,0); adler = upx_adler32(ph.saved_c_adler, in, ph.c_len);
adler = upx_adler32(adler,in,ph.c_len);
if (adler != ph.c_adler) if (adler != ph.c_adler)
throwChecksumError(); throwChecksumError();
} }
@@ -320,8 +315,7 @@ void Packer::decompress(const upx_bytep in, upx_bytep out,
// verify checksum of decompressed data // verify checksum of decompressed data
if (verify_checksum) if (verify_checksum)
{ {
adler = upx_adler32(0,NULL,0); adler = upx_adler32(ph.saved_u_adler, out, ph.u_len);
adler = upx_adler32(adler,out,ph.u_len);
if (adler != ph.u_adler) if (adler != ph.u_adler)
throwChecksumError(); throwChecksumError();
} }
@@ -360,18 +354,16 @@ bool Packer::testOverlappingDecompression(const upx_bytep buf,
} }
void Packer::verifyOverlappingDecompression(MemBuffer *buf, void Packer::verifyOverlappingDecompression()
unsigned overlap_overhead)
{ {
#if defined(UNUPX) assert(ph.c_len < ph.u_len);
#else assert((int)ph.overlap_overhead > 0);
// FIXME (well, this is complete paranoia anyway) #if 1 && !defined(UNUPX)
//
// Idea: // 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 // its contents are no longer needed, i.e. the compressed data
// must have been already written. // 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. // verify the checksum.
// //
// Note: // Note:
@@ -381,9 +373,15 @@ void Packer::verifyOverlappingDecompression(MemBuffer *buf,
// //
// See also: // See also:
// Filter::verifyUnfilter() // Filter::verifyUnfilter()
#endif
UNUSED(buf); if (ph.level == 1)
UNUSED(overlap_overhead); 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) void Packer::checkOverlay(unsigned overlay)
{ {
assert((int)overlay >= 0); assert((off_t)overlay >= 0);
assert((off_t)overlay < file_size); assert((off_t)overlay < file_size);
if (overlay == 0) if (overlay == 0)
return; return;
@@ -566,7 +564,7 @@ void Packer::initPackHeader()
ph.format = getFormat(); ph.format = getFormat();
ph.method = -1; ph.method = -1;
ph.level = -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.buf_offset = -1;
ph.u_file_size = file_size; ph.u_file_size = file_size;
} }
+5 -2
View File
@@ -75,6 +75,10 @@ public:
int filter_cto; int filter_cto;
int header_checksum; int header_checksum;
//
unsigned saved_u_adler;
unsigned saved_c_adler;
// info fields set by fillPackHeader() // info fields set by fillPackHeader()
long buf_offset; long buf_offset;
@@ -178,8 +182,7 @@ protected:
unsigned range = 0, unsigned range = 0,
unsigned upper_limit = ~0u) const; unsigned upper_limit = ~0u) const;
// destructive decompress + verify // destructive decompress + verify
virtual void verifyOverlappingDecompression(MemBuffer *buf, virtual void verifyOverlappingDecompression();
unsigned overlap_overhead);
// packheader handling // packheader handling