src: major cleanups, introduce new eXtended Span class

- initial minimally invasive eXtended Span implementation
- rename ptr_diff to ptr_diff_bytes
- move some files to util subdir
- lots of cleanups
- start using the new checked pointers - this needs some real-world testing
This commit is contained in:
Markus F.X.J. Oberhumer
2022-09-11 16:03:56 +02:00
parent 4318cc22ee
commit c75d7a685d
54 changed files with 3521 additions and 1196 deletions
+56 -51
View File
@@ -180,7 +180,7 @@ int forced_method(int method) // extract the forced method
// compress - wrap call to low-level upx_compress()
**************************************************************************/
bool Packer::compress(upx_bytep i_ptr, unsigned i_len, upx_bytep o_ptr,
bool Packer::compress(SPAN_P(upx_byte) i_ptr, unsigned i_len, SPAN_P(upx_byte) o_ptr,
const upx_compress_config_t *cconf_parm) {
ph.u_len = i_len;
ph.c_len = 0;
@@ -194,7 +194,7 @@ bool Packer::compress(upx_bytep i_ptr, unsigned i_len, upx_bytep o_ptr,
ph.saved_u_adler = ph.u_adler;
ph.saved_c_adler = ph.c_adler;
// update checksum of uncompressed data
ph.u_adler = upx_adler32(i_ptr, ph.u_len, ph.u_adler);
ph.u_adler = upx_adler32(raw_bytes(i_ptr, ph.u_len), ph.u_len, ph.u_adler);
// set compression parameters
upx_compress_config_t cconf;
@@ -241,8 +241,8 @@ bool Packer::compress(upx_bytep i_ptr, unsigned i_len, upx_bytep o_ptr,
// OutputFile::dump("data.raw", in, ph.u_len);
// compress
int r = upx_compress(i_ptr, ph.u_len, o_ptr, &ph.c_len, uip->getCallback(), method, ph.level,
&cconf, &ph.compress_result);
int r = upx_compress(raw_bytes(i_ptr, ph.u_len), ph.u_len, raw_bytes(o_ptr, 0), &ph.c_len,
uip->getCallback(), method, ph.level, &cconf, &ph.compress_result);
// uip->finalCallback(ph.u_len, ph.c_len);
uip->endCallback();
@@ -277,12 +277,13 @@ bool Packer::compress(upx_bytep i_ptr, unsigned i_len, upx_bytep o_ptr,
return false;
// update checksum of compressed data
ph.c_adler = upx_adler32(o_ptr, ph.c_len, ph.c_adler);
ph.c_adler = upx_adler32(raw_bytes(o_ptr, ph.c_len), ph.c_len, ph.c_adler);
// Decompress and verify. Skip this when using the fastest level.
if (!ph_skipVerify(ph)) {
// decompress
unsigned new_len = ph.u_len;
r = upx_decompress(o_ptr, ph.c_len, i_ptr, &new_len, method, &ph.compress_result);
r = upx_decompress(raw_bytes(o_ptr, ph.c_len), ph.c_len, raw_bytes(i_ptr, ph.u_len),
&new_len, method, &ph.compress_result);
if (r == UPX_E_OUT_OF_MEMORY)
throwOutOfMemoryException();
// printf("%d %d: %d %d %d\n", method, r, ph.c_len, ph.u_len, new_len);
@@ -292,7 +293,7 @@ bool Packer::compress(upx_bytep i_ptr, unsigned i_len, upx_bytep o_ptr,
throwInternalError("decompression failed (size error)");
// verify decompression
if (ph.u_adler != upx_adler32(i_ptr, ph.u_len, ph.saved_u_adler))
if (ph.u_adler != upx_adler32(raw_bytes(i_ptr, ph.u_len), ph.u_len, ph.saved_u_adler))
throwInternalError("decompression failed (checksum error)");
}
return true;
@@ -340,13 +341,13 @@ bool Packer::checkFinalCompressionRatio(const OutputFile *fo) const {
// decompress
**************************************************************************/
void ph_decompress(PackHeader &ph, const upx_bytep in, upx_bytep out, bool verify_checksum,
Filter *ft) {
void ph_decompress(PackHeader &ph, SPAN_P(const upx_byte) in, SPAN_P(upx_byte) out,
bool verify_checksum, Filter *ft) {
unsigned adler;
// verify checksum of compressed data
if (verify_checksum) {
adler = upx_adler32(in, ph.c_len, ph.saved_c_adler);
adler = upx_adler32(raw_bytes(in, ph.c_len), ph.c_len, ph.saved_c_adler);
if (adler != ph.c_adler)
throwChecksumError();
}
@@ -356,8 +357,8 @@ void ph_decompress(PackHeader &ph, const upx_bytep in, upx_bytep out, bool verif
throwCantUnpack("header corrupted");
}
unsigned new_len = ph.u_len;
int r =
upx_decompress(in, ph.c_len, out, &new_len, forced_method(ph.method), &ph.compress_result);
int r = upx_decompress(raw_bytes(in, ph.c_len), ph.c_len, raw_bytes(out, ph.u_len), &new_len,
forced_method(ph.method), &ph.compress_result);
if (r == UPX_E_OUT_OF_MEMORY)
throwOutOfMemoryException();
if (r != UPX_E_OK || new_len != ph.u_len)
@@ -366,14 +367,15 @@ void ph_decompress(PackHeader &ph, const upx_bytep in, upx_bytep out, bool verif
// verify checksum of decompressed data
if (verify_checksum) {
if (ft)
ft->unfilter(out, ph.u_len);
adler = upx_adler32(out, ph.u_len, ph.saved_u_adler);
ft->unfilter(raw_bytes(out, ph.u_len), ph.u_len);
adler = upx_adler32(raw_bytes(out, ph.u_len), ph.u_len, ph.saved_u_adler);
if (adler != ph.u_adler)
throwChecksumError();
}
}
void Packer::decompress(const upx_bytep in, upx_bytep out, bool verify_checksum, Filter *ft) {
void Packer::decompress(SPAN_P(const upx_byte) in, SPAN_P(upx_byte) out, bool verify_checksum,
Filter *ft) {
ph_decompress(ph, in, out, verify_checksum, ft);
}
@@ -535,10 +537,10 @@ void Packer::checkOverlay(unsigned overlay) {
throw OverlayException("file has overlay -- skipped; try '--overlay=copy'");
}
void Packer::copyOverlay(OutputFile *fo, unsigned overlay, MemBuffer *buf, bool do_seek) {
void Packer::copyOverlay(OutputFile *fo, unsigned overlay, MemBuffer &buf, bool do_seek) {
assert((int) overlay >= 0);
assert(overlay < file_size_u);
buf->checkState();
buf.checkState();
if (!fo || overlay == 0)
return;
if (opt->overlay != opt->COPY_OVERLAY) {
@@ -551,7 +553,7 @@ void Packer::copyOverlay(OutputFile *fo, unsigned overlay, MemBuffer *buf, bool
fi->seek(-(upx_off_t) overlay, SEEK_END);
// get buffer size, align to improve i/o speed
unsigned buf_size = buf->getSize();
unsigned buf_size = buf.getSize();
if (buf_size > 65536)
buf_size = ALIGN_DOWN(buf_size, 4096u);
assert((int) buf_size > 0);
@@ -562,7 +564,7 @@ void Packer::copyOverlay(OutputFile *fo, unsigned overlay, MemBuffer *buf, bool
fo->write(buf, len);
overlay -= len;
} while (overlay > 0);
buf->checkState();
buf.checkState();
}
// Create a pseudo-unique program id.
@@ -643,14 +645,15 @@ int Packer::patchPackHeader(void *b, int blen) {
int boff = find_le32(b, blen, UPX_MAGIC_LE32);
checkPatch(b, blen, boff, size);
unsigned char *p = (unsigned char *) b + boff;
ph.putPackHeader(p);
auto bb = (upx_byte *) b;
ph.putPackHeader(SPAN_S_MAKE(upx_byte, bb + boff, blen, bb));
return boff;
}
bool Packer::getPackHeader(void const *b, int blen, bool allow_incompressible) {
if (!ph.fillPackHeader((unsigned char const *) b, blen))
bool Packer::getPackHeader(const void *b, int blen, bool allow_incompressible) {
auto bb = (const upx_byte *) b;
if (!ph.fillPackHeader(SPAN_S_MAKE(const upx_byte, bb, blen), blen))
return false;
if (ph.version > getVersion())
@@ -825,18 +828,19 @@ int Packer::patch_le32(void *b, int blen, const void *old, unsigned new_) {
// relocation util
**************************************************************************/
upx_byte *Packer::optimizeReloc(upx_byte *in, unsigned relocnum, upx_byte *out, upx_byte *image,
unsigned headway, int bswap, int *big, int bits) {
unsigned Packer::optimizeReloc(SPAN_P(upx_byte) in, unsigned relocnum, SPAN_P(upx_byte) out,
SPAN_P(upx_byte) image, unsigned headway, bool bswap, int *big,
int bits) {
if (opt->exact)
throwCantPackExact();
*big = 0;
if (relocnum == 0)
return out;
qsort(in, relocnum, 4, le32_compare);
return 0;
qsort(raw_bytes(in, 4 * relocnum), relocnum, 4, le32_compare);
unsigned jc, pc, oc;
upx_byte *fix = out;
SPAN_P_VAR(upx_byte, fix, out);
pc = (unsigned) -4;
for (jc = 0; jc < relocnum; jc++) {
@@ -875,36 +879,35 @@ upx_byte *Packer::optimizeReloc(upx_byte *in, unsigned relocnum, upx_byte *out,
}
}
*fix++ = 0;
return fix;
return ptr_udiff_bytes(fix, out);
}
upx_byte *Packer::optimizeReloc32(upx_byte *in, unsigned relocnum, upx_byte *out, upx_byte *image,
unsigned headway, int bswap, int *big) {
unsigned Packer::optimizeReloc32(SPAN_P(upx_byte) in, unsigned relocnum, SPAN_P(upx_byte) out,
SPAN_P(upx_byte) image, unsigned headway, bool bswap, int *big) {
return optimizeReloc(in, relocnum, out, image, headway, bswap, big, 32);
}
upx_byte *Packer::optimizeReloc64(upx_byte *in, unsigned relocnum, upx_byte *out, upx_byte *image,
unsigned headway, int bswap, int *big) {
unsigned Packer::optimizeReloc64(SPAN_P(upx_byte) in, unsigned relocnum, SPAN_P(upx_byte) out,
SPAN_P(upx_byte) image, unsigned headway, bool bswap, int *big) {
return optimizeReloc(in, relocnum, out, image, headway, bswap, big, 64);
}
unsigned Packer::unoptimizeReloc(upx_byte **in, upx_byte *image, MemBuffer *out, int bswap,
int bits) {
upx_byte *p;
unsigned Packer::unoptimizeReloc(SPAN_P(upx_byte) & in, SPAN_P(upx_byte) image, MemBuffer &out,
bool bswap, int bits) {
SPAN_P_VAR(upx_byte, p, in);
unsigned relocn = 0;
for (p = *in; *p; p++, relocn++)
for (; *p; p++, relocn++)
if (*p >= 0xF0) {
if (*p == 0xF0 && get_le16(p + 1) == 0)
p += 4;
p += 2;
}
upx_byte const *in_end = p;
SPAN_P_VAR(upx_byte, const in_end, p);
// fprintf(stderr,"relocnum=%x\n",relocn);
out->alloc(4 * relocn + 4); // one extra data
LE32 *const outp = (LE32 *) (unsigned char *) *out;
LE32 *relocs = outp;
out.alloc(4 * (relocn + 1)); // one extra entry
SPAN_S_VAR(LE32, relocs, out);
unsigned jc = (unsigned) -4;
for (p = *in; p < in_end; p++) {
for (p = in; p < in_end; p++) {
if (*p < 0xF0)
jc += *p;
else {
@@ -920,32 +923,34 @@ unsigned Packer::unoptimizeReloc(upx_byte **in, upx_byte *image, MemBuffer *out,
if (!relocn--) {
break;
}
if (bswap && image) {
if (bswap && image != nullptr) {
if (bits == 32) {
set_be32(image + jc, get_le32(image + jc));
if ((size_t)(p - (image + jc)) < 4) {
if ((unsigned) ptr_diff_bytes(p, image + jc) < 4) {
// data must not overlap control
p = (4 - 1) + image + jc; // -1: 'for' also increments
p = image + jc + (4 - 1); // -1: 'for' also increments
}
} else if (bits == 64) {
set_be64(image + jc, get_le64(image + jc));
if ((size_t)(p - (image + jc)) < 8) {
if ((unsigned) ptr_diff_bytes(p, image + jc) < 8) {
// data must not overlap control
p = (8 - 1) + image + jc; // -1: 'for' also increments
p = image + jc + (8 - 1); // -1: 'for' also increments
}
} else
throwInternalError("unoptimizeReloc problem");
}
}
*in = p + 1;
return (unsigned) (relocs - outp);
in = p + 1;
return ptr_udiff_bytes(relocs, out);
}
unsigned Packer::unoptimizeReloc32(upx_byte **in, upx_byte *image, MemBuffer *out, int bswap) {
unsigned Packer::unoptimizeReloc32(SPAN_P(upx_byte) & in, SPAN_P(upx_byte) image, MemBuffer &out,
bool bswap) {
return unoptimizeReloc(in, image, out, bswap, 32);
}
unsigned Packer::unoptimizeReloc64(upx_byte **in, upx_byte *image, MemBuffer *out, int bswap) {
unsigned Packer::unoptimizeReloc64(SPAN_P(upx_byte) & in, SPAN_P(upx_byte) image, MemBuffer &out,
bool bswap) {
return unoptimizeReloc(in, image, out, bswap, 64);
}