src: refactoring: create packhead.h and move some methods

This commit is contained in:
Markus F.X.J. Oberhumer
2023-08-11 03:57:20 +02:00
parent c65c882ecc
commit 777d4f5279
7 changed files with 217 additions and 174 deletions
+101 -2
View File
@@ -26,7 +26,8 @@
*/
#include "conf.h"
#include "packer.h"
#include "packhead.h"
#include "filter.h" // for ft->unfilter()
/*************************************************************************
// PackHeader
@@ -92,7 +93,7 @@ int PackHeader::getPackHeaderSize() const {
// see stub/header.ash
**************************************************************************/
void PackHeader::putPackHeader(SPAN_S(byte) p) {
void PackHeader::putPackHeader(SPAN_S(byte) p) const {
// NOTE: It is the caller's responsbility to ensure the buffer p has
// sufficient space for the header.
assert(get_le32(p) == UPX_MAGIC_LE32);
@@ -277,4 +278,102 @@ bool PackHeader::decodePackHeaderFromBuf(SPAN_S(const byte) buf, int blen) {
return true;
}
/*************************************************************************
// ph method util
**************************************************************************/
bool ph_is_forced_method(int method) noexcept // predicate
{
return (method >> 24) == -0x80;
}
int ph_force_method(int method) noexcept // mark as forced
{
return method | (0x80u << 24);
}
int ph_forced_method(int method) noexcept // extract the forced method
{
if (ph_is_forced_method(method))
method &= ~(0x80u << 24);
assert_noexcept(method > 0);
return method;
}
bool ph_skipVerify(const PackHeader &ph) noexcept {
if (M_IS_DEFLATE(ph.method))
return false;
if (M_IS_LZMA(ph.method))
return false;
if (ph.level > 1)
return false;
return true;
}
/*************************************************************************
// ph decompress util
**************************************************************************/
void ph_decompress(PackHeader &ph, SPAN_P(const byte) in, SPAN_P(byte) out, bool verify_checksum,
Filter *ft) {
// verify checksum of compressed data
if (verify_checksum) {
unsigned adler = upx_adler32(raw_bytes(in, ph.c_len), ph.c_len, ph.saved_c_adler);
if (adler != ph.c_adler)
throwChecksumError();
}
// decompress
if (ph.u_len < ph.c_len)
throwCantUnpack("header corrupted");
unsigned new_len = ph.u_len;
int r = upx_decompress(raw_bytes(in, ph.c_len), ph.c_len, raw_bytes(out, ph.u_len), &new_len,
ph_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)
throwCompressedDataViolation();
// verify checksum of decompressed data
if (verify_checksum) {
if (ft)
ft->unfilter(out, ph.u_len);
unsigned adler = upx_adler32(raw_bytes(out, ph.u_len), ph.u_len, ph.saved_u_adler);
if (adler != ph.u_adler)
throwChecksumError();
}
}
/*************************************************************************
// ph overlapping decompression util
**************************************************************************/
bool ph_testOverlappingDecompression(const PackHeader &ph, const byte *buf, const byte *tbuf,
unsigned overlap_overhead) {
if (ph.c_len >= ph.u_len)
return false;
assert((int) overlap_overhead >= 0);
assert((int) (ph.u_len + overlap_overhead) >= 0);
const int method = ph_forced_method(ph.method);
// Because upx_test_overlap() does not use the asm_fast decompressor
// we must account for extra 3 bytes that asm_fast does use,
// or else we may fail at runtime decompression.
unsigned extra = 0;
if (M_IS_NRV2B(method) || M_IS_NRV2D(method) || M_IS_NRV2E(method))
extra = 3;
if (overlap_overhead <= 4 + extra) // don't waste time here
return false;
overlap_overhead -= extra;
unsigned src_off = ph.u_len + overlap_overhead - ph.c_len;
unsigned new_len = ph.u_len;
int r = upx_test_overlap(buf - src_off, tbuf, src_off, ph.c_len, &new_len, method,
&ph.compress_result);
if (r == UPX_E_OUT_OF_MEMORY)
throwOutOfMemoryException();
return (r == UPX_E_OK && new_len == ph.u_len);
}
/* vim:set ts=4 sw=4 et: */