int upx_decompress ( const upx_bytep src, unsigned src_len, upx_bytep dst, unsigned* dst_len, int method, const upx_compress_result_t *cresult ) { int r = UPX_E_ERROR; assert(*dst_len > 0); assert(src_len < *dst_len); // must be compressed if (cresult && cresult->method == 0) cresult = NULL; if (0) { } #if (WITH_LZMA) else if (M_IS_LZMA(method)) r = upx_lzma_decompress(src, src_len, dst, dst_len, method, cresult); #endif #if (WITH_NRV) else if (M_IS_NRV2B(method) || M_IS_NRV2D(method) || M_IS_NRV2E(method)) r = upx_nrv_decompress(src, src_len, dst, dst_len, method, cresult); #endif #if (WITH_UCL) else if (M_IS_NRV2B(method) || M_IS_NRV2D(method) || M_IS_NRV2E(method)) r = upx_ucl_decompress(src, src_len, dst, dst_len, method, cresult); #endif #if (WITH_ZLIB) else if (M_IS_DEFLATE(method)) r = upx_zlib_decompress(src, src_len, dst, dst_len, method, cresult); #endif else { throwInternalError("unknown decompression method"); } return r; }
int upx_zlib_test_overlap ( const upx_bytep buf, const upx_bytep tbuf, unsigned src_off, unsigned src_len, unsigned* dst_len, int method, const upx_compress_result_t *cresult ) { assert(method == M_DEFLATE); MemBuffer b(src_off + src_len); memcpy(b + src_off, buf + src_off, src_len); unsigned saved_dst_len = *dst_len; int r = upx_zlib_decompress(b + src_off, src_len, b, dst_len, method, cresult); if (r != UPX_E_OK) return r; if (*dst_len != saved_dst_len) return UPX_E_ERROR; // NOTE: there is a very tiny possibility that decompression has // succeeded but the data is not restored correctly because of // in-place buffer overlapping, so we use an extra memcmp(). if (tbuf != NULL && memcmp(tbuf, b, *dst_len) != 0) return UPX_E_ERROR; return UPX_E_OK; }