Cleanup "PT_LOAD gap recovery" during upx -d
https://github.com/upx/upx/issues/635 modified: p_lx_elf.cpp
This commit is contained in:
committed by
Markus F.X.J. Oberhumer
parent
0ac3cb2329
commit
fefce0d5c4
+32
-26
@@ -5405,34 +5405,40 @@ void PackLinuxElf64::unpack(OutputFile *fo)
|
|||||||
get_te64(&phdr[j].p_filesz);
|
get_te64(&phdr[j].p_filesz);
|
||||||
if (fo)
|
if (fo)
|
||||||
fo->seek(where, SEEK_SET);
|
fo->seek(where, SEEK_SET);
|
||||||
{ // Recover from some piracy [also serves as error tolerance :-) ]
|
{ // Recover from some piracy [also serves as error tolerance :-) ]
|
||||||
b_info b_peek;
|
b_info b_peek;
|
||||||
fi->readx(&b_peek, sizeof(b_peek));
|
fi->readx(&b_peek, sizeof(b_peek));
|
||||||
upx_off_t pos = fi->seek(-(off_t)sizeof(b_peek), SEEK_CUR);
|
upx_off_t pos = fi->seek(-(off_t)sizeof(b_peek), SEEK_CUR);
|
||||||
if (b_peek.sz_unc != size
|
if (get_te32(&b_peek.sz_unc) != size
|
||||||
|| b_peek.b_method != prev_method) {
|
|| b_peek.b_method != prev_method) {
|
||||||
opt->info_mode++;
|
opt->info_mode++;
|
||||||
infoWarning("bad b_info at %#zx", (size_t)pos);
|
infoWarning("bad b_info at %#zx", (size_t)pos);
|
||||||
unsigned const N_PEEK(64), H_PEEK(N_PEEK >> 1);
|
unsigned const N_PEEK(64), H_PEEK(N_PEEK >> 1);
|
||||||
unsigned char peek_arr[N_PEEK];
|
unsigned char peek_arr[N_PEEK];
|
||||||
fi->seek(pos - H_PEEK, SEEK_SET);
|
fi->seek(pos - H_PEEK, SEEK_SET);
|
||||||
fi->readx(peek_arr, sizeof(peek_arr));
|
fi->readx(peek_arr, sizeof(peek_arr));
|
||||||
fi->seek(pos + H_PEEK - sizeof(peek_arr), SEEK_SET);
|
|
||||||
int boff = find_le32(peek_arr, sizeof(peek_arr), size);
|
|
||||||
unsigned word1 = get_te32(&peek_arr[0*sizeof(int) + boff]);
|
|
||||||
unsigned word2 = get_te32(&peek_arr[1*sizeof(int) + boff]);
|
|
||||||
unsigned word3 = get_te32(&peek_arr[2*sizeof(int) + boff]);
|
|
||||||
if (0 <= boff // found
|
|
||||||
&& (((0 == word3) && (word1 == word2)) // uncompressible literal
|
|
||||||
|| prev_method == word3) // same method, no filter
|
|
||||||
) {
|
|
||||||
pos -= H_PEEK;
|
|
||||||
pos += boff;
|
|
||||||
infoWarning("... recovery at %#zx", (size_t)pos);
|
|
||||||
fi->seek(pos, SEEK_SET);
|
fi->seek(pos, SEEK_SET);
|
||||||
|
int boff = find_le32(peek_arr, sizeof(peek_arr), size);
|
||||||
|
b_info *bp = (b_info *)(void *)&peek_arr[boff];
|
||||||
|
|
||||||
|
unsigned sz_unc = get_te32(&bp->sz_unc);
|
||||||
|
unsigned sz_cpr = get_te32(&bp->sz_cpr);
|
||||||
|
unsigned word3 = get_te32(&bp->b_method);
|
||||||
|
unsigned method = bp->b_method;
|
||||||
|
unsigned ftid = bp->b_ftid;
|
||||||
|
unsigned cto8 = bp->b_cto8;
|
||||||
|
if (0 <= boff // found
|
||||||
|
&& (((sz_unc == sz_cpr) && (0 == word3))// uncompressible literal
|
||||||
|
|| ((sz_cpr < sz_unc) && (method == prev_method)
|
||||||
|
&& (0 == ftid) && (0 == cto8)))
|
||||||
|
) {
|
||||||
|
pos -= H_PEEK;
|
||||||
|
pos += boff;
|
||||||
|
infoWarning("... recovery at %#zx", (size_t)pos);
|
||||||
|
fi->seek(pos, SEEK_SET);
|
||||||
|
}
|
||||||
|
opt->info_mode--;
|
||||||
}
|
}
|
||||||
opt->info_mode--;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
unpackExtent(size, fo,
|
unpackExtent(size, fo,
|
||||||
c_adler, u_adler, false, szb_info,
|
c_adler, u_adler, false, szb_info,
|
||||||
|
|||||||
Reference in New Issue
Block a user