From 572082ac2bc983311aa309b94270991cd9f1a95d Mon Sep 17 00:00:00 2001 From: "Markus F.X.J. Oberhumer" Date: Tue, 2 Jan 2001 19:58:28 +0000 Subject: [PATCH] Implemented Packer::verifyOverlappingDecompression(). committer: mfx 978465508 +0000 --- TODO | 2 ++ src/mem.cpp | 10 +------- src/mem.h | 2 -- src/p_com.cpp | 2 +- src/p_djgpp2.cpp | 2 +- src/p_exe.cpp | 2 +- src/p_lx_elf.cpp | 8 +++--- src/p_tmt.cpp | 2 +- src/p_tos.cpp | 2 +- src/p_unix.cpp | 8 +++--- src/p_vmlinz.cpp | 2 +- src/p_w32pe.cpp | 3 +++ src/packer.cpp | 64 +++++++++++++++++++++++------------------------- src/packer.h | 7 ++++-- 14 files changed, 58 insertions(+), 58 deletions(-) diff --git a/TODO b/TODO index fcf573b5..9c40c6f9 100644 --- a/TODO +++ b/TODO @@ -77,6 +77,8 @@ FORMAT WATCOM/LE - implement compressWithFilters() +- add a call to verifyOverlappingDecompression() + FORMAT WIN32/PE =============== diff --git a/src/mem.cpp b/src/mem.cpp index 1dd1d9ec..1c1c404f 100644 --- a/src/mem.cpp +++ b/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); } diff --git a/src/mem.h b/src/mem.h index 1fb1a800..cfab03bc 100644 --- a/src/mem.h +++ b/src/mem.h @@ -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); diff --git a/src/p_com.cpp b/src/p_com.cpp index 883f25b1..a807dac0 100644 --- a/src/p_com.cpp +++ b/src/p_com.cpp @@ -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)) diff --git a/src/p_djgpp2.cpp b/src/p_djgpp2.cpp index 4ab703c5..e4535fbb 100644 --- a/src/p_djgpp2.cpp +++ b/src/p_djgpp2.cpp @@ -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 diff --git a/src/p_exe.cpp b/src/p_exe.cpp index 1935daf2..b775c917 100644 --- a/src/p_exe.cpp +++ b/src/p_exe.cpp @@ -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); diff --git a/src/p_lx_elf.cpp b/src/p_lx_elf.cpp index 100daa17..1fcbea23 100644 --- a/src/p_lx_elf.cpp +++ b/src/p_lx_elf.cpp @@ -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); diff --git a/src/p_tmt.cpp b/src/p_tmt.cpp index aabf1eb2..67856a4c 100644 --- a/src/p_tmt.cpp +++ b/src/p_tmt.cpp @@ -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); diff --git a/src/p_tos.cpp b/src/p_tos.cpp index 61d22d96..a284cfad 100644 --- a/src/p_tos.cpp +++ b/src/p_tos.cpp @@ -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); diff --git a/src/p_unix.cpp b/src/p_unix.cpp index 0316c181..a872f57b 100644 --- a/src/p_unix.cpp +++ b/src/p_unix.cpp @@ -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); diff --git a/src/p_vmlinz.cpp b/src/p_vmlinz.cpp index b1165ca8..1ad0dc2d 100644 --- a/src/p_vmlinz.cpp +++ b/src/p_vmlinz.cpp @@ -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)) diff --git a/src/p_w32pe.cpp b/src/p_w32pe.cpp index a1270170..9fd576fb 100644 --- a/src/p_w32pe.cpp +++ b/src/p_w32pe.cpp @@ -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); diff --git a/src/packer.cpp b/src/packer.cpp index 8020622e..983b2ea3 100644 --- a/src/packer.cpp +++ b/src/packer.cpp @@ -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) diff --git a/src/packer.h b/src/packer.h index 5192c3aa..2d06a80d 100644 --- a/src/packer.h +++ b/src/packer.h @@ -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