mirror of
https://github.com/upx/upx
synced 2025-09-28 19:06:07 +08:00
Detect bad b_info.method
https://issues.oss-fuzz.com/u/1/issues?q=upx modified: p_lx_elf.cpp modified: p_unix.cpp modified: packhead.cpp modified: packhead.h
This commit is contained in:
parent
896dff9619
commit
8cce9cf641
|
@ -4300,7 +4300,7 @@ void PackLinuxElf32::pack1(OutputFile * /*fo*/, Filter &ft)
|
|||
fi->readx(ibuf, filesz);
|
||||
ft = orig_ft;
|
||||
ph = orig_ph;
|
||||
ph.method = ph_force_method(methods[k]);
|
||||
ph.set_method(ph_force_method(methods[k]), offset);
|
||||
ph.u_len = filesz;
|
||||
compressWithFilters(&ft, OVERHEAD, NULL_cconf, 10, true);
|
||||
sz_this += ph.c_len;
|
||||
|
@ -4313,7 +4313,7 @@ void PackLinuxElf32::pack1(OutputFile * /*fo*/, Filter &ft)
|
|||
fi->readx(ibuf, sz_tail);
|
||||
ft = orig_ft;
|
||||
ph = orig_ph;
|
||||
ph.method = ph_force_method(methods[k]);
|
||||
ph.set_method(ph_force_method(methods[k]));
|
||||
ph.u_len = sz_tail;
|
||||
compressWithFilters(&ft, OVERHEAD, NULL_cconf, 10, true);
|
||||
sz_this += ph.c_len;
|
||||
|
@ -4326,7 +4326,7 @@ void PackLinuxElf32::pack1(OutputFile * /*fo*/, Filter &ft)
|
|||
}
|
||||
ft = orig_ft;
|
||||
ph = orig_ph;
|
||||
ph.method = ph_force_method(method_best);
|
||||
ph.set_method(ph_force_method(method_best));
|
||||
}
|
||||
|
||||
Elf32_Phdr *phdr = phdri;
|
||||
|
@ -5152,7 +5152,7 @@ void PackLinuxElf64::pack1(OutputFile * /*fo*/, Filter &ft)
|
|||
fi->readx(ibuf, filesz);
|
||||
ft = orig_ft;
|
||||
ph = orig_ph;
|
||||
ph.method = ph_force_method(methods[k]);
|
||||
ph.set_method(ph_force_method(methods[k]));
|
||||
ph.u_len = filesz;
|
||||
compressWithFilters(&ft, OVERHEAD, NULL_cconf, 10, true);
|
||||
sz_this += ph.c_len;
|
||||
|
@ -5165,7 +5165,7 @@ void PackLinuxElf64::pack1(OutputFile * /*fo*/, Filter &ft)
|
|||
fi->readx(ibuf, sz_tail);
|
||||
ft = orig_ft;
|
||||
ph = orig_ph;
|
||||
ph.method = ph_force_method(methods[k]);
|
||||
ph.set_method(ph_force_method(methods[k]));
|
||||
ph.u_len = sz_tail;
|
||||
compressWithFilters(&ft, OVERHEAD, NULL_cconf, 10, true);
|
||||
sz_this += ph.c_len;
|
||||
|
@ -5178,7 +5178,7 @@ void PackLinuxElf64::pack1(OutputFile * /*fo*/, Filter &ft)
|
|||
}
|
||||
ft = orig_ft;
|
||||
ph = orig_ph;
|
||||
ph.method = ph_force_method(method_best);
|
||||
ph.set_method(ph_force_method(method_best));
|
||||
}
|
||||
|
||||
Elf64_Phdr *phdr = phdri;
|
||||
|
@ -7620,7 +7620,7 @@ void PackLinuxElf64::unpack(OutputFile *fo)
|
|||
fi->readx(&bhdr, szb_info);
|
||||
ph.u_len = get_te32(&bhdr.sz_unc);
|
||||
ph.c_len = get_te32(&bhdr.sz_cpr);
|
||||
ph.method = bhdr.b_method;
|
||||
ph.set_method(bhdr.b_method, overlay_offset + sizeof(p_info));
|
||||
if (ph.c_len > file_size_u || ph.c_len == 0 || ph.u_len == 0
|
||||
|| ph.u_len > orig_file_size)
|
||||
throwCantUnpack("b_info corrupted");
|
||||
|
@ -7665,11 +7665,11 @@ void PackLinuxElf64::unpack(OutputFile *fo)
|
|||
unsigned b_method = ibuf[0];
|
||||
unsigned b_extra = ibuf[3];
|
||||
if (M_ZSTD >= b_method && 0 == b_extra) {
|
||||
fi->seek( -(upx_off_t)(ph.c_len + szb_info), SEEK_CUR);
|
||||
unsigned where = fi->seek( -(upx_off_t)(ph.c_len + szb_info), SEEK_CUR);
|
||||
szb_info = 12;
|
||||
fi->readx(&bhdr, szb_info);
|
||||
ph.filter_cto = bhdr.b_cto8;
|
||||
ph.method = bhdr.b_method;
|
||||
ph.set_method(bhdr.b_method, where);
|
||||
prev_method = bhdr.b_method; // FIXME if multiple de-compressors
|
||||
fi->readx(ibuf, ph.c_len);
|
||||
}
|
||||
|
@ -7867,7 +7867,7 @@ void PackLinuxElf64::unpack(OutputFile *fo)
|
|||
|
||||
// check for end-of-file
|
||||
fi->readx(&bhdr, szb_info);
|
||||
ph.method = bhdr.b_method;
|
||||
ph.set_method(bhdr.b_method, ~0u);
|
||||
unsigned const sz_unc = ph.u_len = get_te32(&bhdr.sz_unc);
|
||||
|
||||
if (sz_unc == 0) { // uncompressed size 0 -> EOF
|
||||
|
@ -8851,7 +8851,7 @@ void PackLinuxElf32::unpack(OutputFile *fo)
|
|||
fi->readx(&bhdr, szb_info);
|
||||
ph.u_len = get_te32(&bhdr.sz_unc);
|
||||
ph.c_len = get_te32(&bhdr.sz_cpr);
|
||||
ph.method = bhdr.b_method;
|
||||
ph.set_method(bhdr.b_method, overlay_offset + sizeof(p_info));
|
||||
if (ph.c_len > (unsigned)file_size || ph.c_len == 0 || ph.u_len == 0
|
||||
|| ph.u_len > orig_file_size)
|
||||
throwCantUnpack("b_info corrupted");
|
||||
|
@ -9076,7 +9076,7 @@ void PackLinuxElf32::unpack(OutputFile *fo)
|
|||
|
||||
// check for end-of-file
|
||||
fi->readx(&bhdr, szb_info);
|
||||
ph.method = bhdr.b_method;
|
||||
ph.set_method(bhdr.b_method, ~0u);
|
||||
unsigned const sz_unc = ph.u_len = get_te32(&bhdr.sz_unc);
|
||||
|
||||
if (sz_unc == 0) { // uncompressed size 0 -> EOF
|
||||
|
|
|
@ -485,7 +485,6 @@ unsigned PackUnix::unpackExtent(unsigned wanted, OutputFile *fo,
|
|||
fi->readx(&hdr, szb_info);
|
||||
int const sz_unc = ph.u_len = get_te32(&hdr.sz_unc);
|
||||
int const sz_cpr = ph.c_len = get_te32(&hdr.sz_cpr);
|
||||
ph.method = hdr.b_method;
|
||||
ph.filter_cto = hdr.b_cto8;
|
||||
|
||||
if (sz_unc == 0 || M_LZMA < hdr.b_method) {
|
||||
|
@ -508,6 +507,7 @@ unsigned PackUnix::unpackExtent(unsigned wanted, OutputFile *fo,
|
|||
c_adler = upx_adler32(ibuf + j, sz_cpr, c_adler);
|
||||
|
||||
if (sz_cpr < sz_unc) { // block was compressed
|
||||
ph.set_method(hdr.b_method);
|
||||
decompress(ibuf+j, ibuf+inlen, false);
|
||||
if (12==szb_info) { // modern per-block filter
|
||||
if (hdr.b_ftid) {
|
||||
|
@ -658,7 +658,7 @@ void PackUnix::unpack(OutputFile *fo)
|
|||
fi->readx(&bhdr, szb_info);
|
||||
ph.u_len = sz_unc = get_te32(&bhdr.sz_unc);
|
||||
ph.c_len = sz_cpr = get_te32(&bhdr.sz_cpr);
|
||||
ph.method = bhdr.b_method;
|
||||
ph.set_method(bhdr.b_method);
|
||||
|
||||
if (sz_unc == 0) // uncompressed size 0 -> EOF
|
||||
{
|
||||
|
|
|
@ -45,6 +45,13 @@ void PackHeader::reset() noexcept {
|
|||
compress_result.reset();
|
||||
}
|
||||
|
||||
int PackHeader::set_method(int m, unsigned offset) {
|
||||
unsigned mc = ~(0x80u << 24) & m; // see ph_forced_method
|
||||
if ((mc < M_NRV2B_LE32 || M_LZMA < mc) && ~0u != offset)
|
||||
throwCantPack("bad method %#x at %#x", (unsigned) m, offset);
|
||||
return method = m;
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
// extremely simple checksum for the header itself (since version 10)
|
||||
**************************************************************************/
|
||||
|
|
|
@ -63,6 +63,7 @@ struct PackHeader final {
|
|||
int n_mru; // specific name for filter ctojr
|
||||
};
|
||||
int header_checksum;
|
||||
int set_method(int m, unsigned offset = 0); // check, then assign
|
||||
|
||||
// support fields for verifying decompression
|
||||
unsigned saved_u_adler;
|
||||
|
|
Loading…
Reference in New Issue
Block a user