From 8232aedf78ef234243dad6fef211219f20755aa5 Mon Sep 17 00:00:00 2001 From: John Reiser Date: Sat, 11 Feb 2017 15:26:27 -0800 Subject: [PATCH] unpackExtent() segregates rewrite() from write() Fix the reported output file size when un-compressing. Part of https://github.com/upx/upx/issues/60 modified: p_lx_elf.cpp modified: p_unix.cpp modified: p_unix.h --- src/p_lx_elf.cpp | 18 ++++++++++++++++-- src/p_unix.cpp | 12 +++++++++--- src/p_unix.h | 2 +- 3 files changed, 26 insertions(+), 6 deletions(-) diff --git a/src/p_lx_elf.cpp b/src/p_lx_elf.cpp index ab75311a..55a1ebe3 100644 --- a/src/p_lx_elf.cpp +++ b/src/p_lx_elf.cpp @@ -3388,6 +3388,12 @@ void PackLinuxElf64::unpack(OutputFile *fo) // The gaps between PT_LOAD and after last PT_LOAD phdr = (Elf64_Phdr *) (u.buf + sizeof(*ehdr)); + upx_uint64_t hi_offset(0); + for (unsigned j = 0; j < u_phnum; ++j) { + if (PT_LOAD64==phdr[j].p_type + && hi_offset < phdr[j].p_offset) + hi_offset = phdr[j].p_offset; + } for (unsigned j = 0; j < u_phnum; ++j) { unsigned const size = find_LOAD_gap(phdr, j, u_phnum); if (size) { @@ -3396,7 +3402,8 @@ void PackLinuxElf64::unpack(OutputFile *fo) if (fo) fo->seek(where, SEEK_SET); unpackExtent(size, fo, total_in, total_out, - c_adler, u_adler, false, szb_info); + c_adler, u_adler, false, szb_info, + (phdr[j].p_offset != hi_offset)); } } @@ -3959,6 +3966,12 @@ void PackLinuxElf32::unpack(OutputFile *fo) // The gaps between PT_LOAD and after last PT_LOAD phdr = (Elf32_Phdr *) (u.buf + sizeof(*ehdr)); + unsigned hi_offset(0); + for (unsigned j = 0; j < u_phnum; ++j) { + if (PT_LOAD32==phdr[j].p_type + && hi_offset < phdr[j].p_offset) + hi_offset = phdr[j].p_offset; + } for (unsigned j = 0; j < u_phnum; ++j) { unsigned const size = find_LOAD_gap(phdr, j, u_phnum); if (size) { @@ -3967,7 +3980,8 @@ void PackLinuxElf32::unpack(OutputFile *fo) if (fo) fo->seek(where, SEEK_SET); unpackExtent(size, fo, total_in, total_out, - c_adler, u_adler, false, szb_info); + c_adler, u_adler, false, szb_info, + (phdr[j].p_offset != hi_offset)); } } diff --git a/src/p_unix.cpp b/src/p_unix.cpp index 695c79b7..99303bbe 100644 --- a/src/p_unix.cpp +++ b/src/p_unix.cpp @@ -448,7 +448,7 @@ void PackUnix::packExtent( void PackUnix::unpackExtent(unsigned wanted, OutputFile *fo, unsigned &total_in, unsigned &total_out, unsigned &c_adler, unsigned &u_adler, - bool first_PF_X, unsigned szb_info + bool first_PF_X, unsigned szb_info, bool is_rewrite ) { b_info hdr; memset(&hdr, 0, sizeof(hdr)); @@ -501,8 +501,14 @@ void PackUnix::unpackExtent(unsigned wanted, OutputFile *fo, total_in += sz_cpr; total_out += sz_unc; // write block - if (fo) - fo->write(ibuf + j, sz_unc); + if (fo) { + if (is_rewrite) { + fo->rewrite(ibuf + j, sz_unc); + } + else { + fo->write(ibuf + j, sz_unc); + } + } if (wanted < (unsigned)sz_unc) throwCantUnpack("corrupt b_info"); wanted -= sz_unc; diff --git a/src/p_unix.h b/src/p_unix.h index 60d93fc2..0d108389 100644 --- a/src/p_unix.h +++ b/src/p_unix.h @@ -77,7 +77,7 @@ protected: virtual void unpackExtent(unsigned wanted, OutputFile *fo, unsigned &total_in, unsigned &total_out, unsigned &c_adler, unsigned &u_adler, - bool first_PF_X, unsigned szb_info ); + bool first_PF_X, unsigned szb_info, bool is_rewrite = false); int exetype; unsigned blocksize;