From a050f82f0e09957f380ded750865f1890ff21dd4 Mon Sep 17 00:00:00 2001 From: "Markus F.X.J. Oberhumer" Date: Tue, 21 Nov 2006 17:19:24 +0100 Subject: [PATCH] Implemented the remaining missing pieces of compress_zlib. --- src/compress.h | 10 +++++ src/compress_zlib.cpp | 89 +++++++++++++++++++++++++++++++++++-------- src/conf.h | 28 +++++++++++++- src/main.cpp | 12 ++++++ src/options.h | 3 +- src/packer.cpp | 6 +++ 6 files changed, 129 insertions(+), 19 deletions(-) diff --git a/src/compress.h b/src/compress.h index 58021967..27e75b1f 100644 --- a/src/compress.h +++ b/src/compress.h @@ -92,10 +92,20 @@ int upx_ucl_test_overlap ( const upx_bytep buf, unsigned src_off, #if defined(WITH_ZLIB) const char *upx_zlib_version_string(void); +int upx_zlib_compress ( const upx_bytep src, unsigned src_len, + upx_bytep dst, unsigned* dst_len, + upx_callback_p cb, + int method, int level, + const upx_compress_config_t *cconf, + upx_compress_result_t *cresult ); int upx_zlib_decompress ( const upx_bytep src, unsigned src_len, upx_bytep dst, unsigned* dst_len, int method, const upx_compress_result_t *cresult ); +int upx_zlib_test_overlap ( const upx_bytep buf, unsigned src_off, + unsigned src_len, unsigned* dst_len, + int method, + const upx_compress_result_t *cresult ); #endif diff --git a/src/compress_zlib.cpp b/src/compress_zlib.cpp index dfb62b3a..7182edb3 100644 --- a/src/compress_zlib.cpp +++ b/src/compress_zlib.cpp @@ -28,6 +28,18 @@ #include "conf.h" #include "compress.h" + + +void zlib_compress_config_t::reset() +{ + memset(this, 0, sizeof(*this)); + + mem_level.reset(); + window_bits.reset(); + strategy.reset(); +} + + #if !defined(WITH_ZLIB) extern int compress_zlib_dummy; int compress_zlib_dummy = 0; @@ -61,24 +73,64 @@ int upx_zlib_compress ( const upx_bytep src, unsigned src_len, { assert(method == M_DEFLATE); assert(level > 0); assert(cresult != NULL); + UNUSED(cb_parm); + int r = UPX_E_ERROR; + int zr; + const zlib_compress_config_t *lcconf = cconf_parm ? &cconf_parm->conf_zlib : NULL; + zlib_compress_result_t *res = &cresult->result_zlib; + + if (level == 10) + level = 9; + + zlib_compress_config_t::mem_level_t mem_level; + zlib_compress_config_t::window_bits_t window_bits; + zlib_compress_config_t::strategy_t strategy; + // cconf overrides + if (lcconf) + { + oassign(mem_level, lcconf->mem_level); + oassign(window_bits, lcconf->window_bits); + oassign(strategy, lcconf->strategy); + } + + res->dummy = 0; z_stream s; s.zalloc = (alloc_func) 0; s.zfree = (free_func) 0; - - s.next_in = (Bytef*) (acc_uintptr_t) src; // UNCONST + s.next_in = const_cast(src); // UNCONST s.avail_in = src_len; s.next_out = dst; s.avail_out = *dst_len; + s.total_in = s.total_out = 0; - UNUSED(src); UNUSED(src_len); - UNUSED(dst); UNUSED(dst_len); - UNUSED(cb_parm); - UNUSED(method); UNUSED(level); - UNUSED(cconf_parm); - UNUSED(cresult); - - return UPX_E_ERROR; + zr = deflateInit2(&s, level, Z_DEFLATED, 0 - (int)window_bits, + mem_level, strategy); + if (zr != Z_OK) + goto error; + zr = deflate(&s, Z_FINISH); + if (zr != Z_STREAM_END) + goto error; + zr = deflateEnd(&s); + if (zr != Z_OK) + goto error; + r = UPX_E_OK; + goto done; +error: + (void) deflateEnd(&s); + r = convert_errno_from_zlib(zr); + if (r == UPX_E_OK) + r = UPX_E_ERROR; +done: + if (r == UPX_E_OK) + { + if (s.avail_in != 0 || s.total_in != src_len) + r = UPX_E_ERROR; + } + assert(s.total_in <= src_len); + assert(s.total_out <= *dst_len); + *dst_len = s.total_out; + return r; } @@ -136,7 +188,7 @@ done: /************************************************************************* -// +// test_overlap **************************************************************************/ int upx_zlib_test_overlap ( const upx_bytep buf, unsigned src_off, @@ -145,13 +197,18 @@ int upx_zlib_test_overlap ( const upx_bytep buf, unsigned src_off, const upx_compress_result_t *cresult ) { assert(method == M_DEFLATE); - UNUSED(cresult); - UNUSED(buf); UNUSED(src_off); - UNUSED(src_len); UNUSED(dst_len); - UNUSED(method); - UNUSED(cresult); + // FIXME - implement this + // Note that Packer::verifyOverlappingDecompression() will + // verify the final result in any case. + UNUSED(buf); + unsigned overlap_overhead = src_off + src_len - *dst_len; + //printf("upx_zlib_test_overlap: %d\n", overlap_overhead); + if ((int)overlap_overhead >= 256) + return UPX_E_OK; + + UNUSED(cresult); return UPX_E_ERROR; } diff --git a/src/conf.h b/src/conf.h index c275195a..3d640bb5 100644 --- a/src/conf.h +++ b/src/conf.h @@ -555,11 +555,26 @@ struct ucl_compress_config_t : public REAL_ucl_compress_config_t }; +struct zlib_compress_config_t +{ + typedef OptVar mem_level_t; // ml + typedef OptVar window_bits_t; // wb + typedef OptVar strategy_t; // st + + mem_level_t mem_level; // ml + window_bits_t window_bits; // wb + strategy_t strategy; // st + + void reset(); +}; + + struct upx_compress_config_t { lzma_compress_config_t conf_lzma; ucl_compress_config_t conf_ucl; - void reset() { conf_lzma.reset(); conf_ucl.reset(); } + zlib_compress_config_t conf_zlib; + void reset() { conf_lzma.reset(); conf_ucl.reset(); conf_zlib.reset(); } }; @@ -590,6 +605,14 @@ struct ucl_compress_result_t }; +struct zlib_compress_result_t +{ + unsigned dummy; + + void reset() { memset(this, 0, sizeof(*this)); } +}; + + struct upx_compress_result_t { // debug @@ -598,10 +621,11 @@ struct upx_compress_result_t lzma_compress_result_t result_lzma; ucl_compress_result_t result_ucl; + zlib_compress_result_t result_zlib; void reset() { memset(this, 0, sizeof(*this)); - result_lzma.reset(); result_ucl.reset(); + result_lzma.reset(); result_ucl.reset(); result_zlib.reset(); } }; diff --git a/src/main.cpp b/src/main.cpp index 7cbf3d79..eddb4cd0 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -680,6 +680,15 @@ static int do_option(int optc, const char *arg) case 816: getoptvar(&opt->crp.crp_lzma.num_fast_bytes, arg); break; + case 821: + getoptvar(&opt->crp.crp_zlib.mem_level, arg); + break; + case 822: + getoptvar(&opt->crp.crp_zlib.window_bits, arg); + break; + case 823: + getoptvar(&opt->crp.crp_zlib.strategy, arg); + break; // backup case 'k': opt->backup = 1; @@ -932,6 +941,9 @@ static const struct mfx_option longopts[] = {"crp-lzma-lc", 0x31, 0, 813}, {"crp-lzma-ds", 0x31, 0, 814}, {"crp-lzma-fb", 0x31, 0, 816}, + {"crp-zlib-ml", 0x31, 0, 821}, + {"crp-zlib-wb", 0x31, 0, 822}, + {"crp-zlib-st", 0x31, 0, 823}, // [deprecated - only for compatibility with UPX 2.0x] {"crp-ms", 0x31, 0, 807}, diff --git a/src/options.h b/src/options.h index ef000e92..735c37a9 100644 --- a/src/options.h +++ b/src/options.h @@ -87,7 +87,8 @@ struct options_t { struct crp_t { lzma_compress_config_t crp_lzma; ucl_compress_config_t crp_ucl; - void reset() { crp_lzma.reset(); crp_ucl.reset(); } + zlib_compress_config_t crp_zlib; + void reset() { crp_lzma.reset(); crp_ucl.reset(); crp_zlib.reset(); } }; crp_t crp; diff --git a/src/packer.cpp b/src/packer.cpp index 8afcef30..f773c671 100644 --- a/src/packer.cpp +++ b/src/packer.cpp @@ -217,6 +217,12 @@ bool Packer::compress(upx_bytep in, upx_bytep out, oassign(cconf.conf_lzma.dict_size, opt->crp.crp_lzma.dict_size); oassign(cconf.conf_lzma.num_fast_bytes, opt->crp.crp_lzma.num_fast_bytes); } + if (M_IS_DEFLATE(ph.method)) + { + oassign(cconf.conf_zlib.mem_level, opt->crp.crp_zlib.mem_level); + oassign(cconf.conf_zlib.window_bits, opt->crp.crp_zlib.window_bits); + oassign(cconf.conf_zlib.strategy, opt->crp.crp_zlib.strategy); + } if (uip->ui_pass >= 0) uip->ui_pass++; uip->startCallback(ph.u_len, step, uip->ui_pass, uip->ui_total_passes);