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
This commit is contained in:
John Reiser 2017-02-11 15:26:27 -08:00
parent d30a0a2e67
commit 8232aedf78
3 changed files with 26 additions and 6 deletions

View File

@ -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));
}
}

View File

@ -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;

View File

@ -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;