⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 p_unix.cpp

📁 UPX 源代码
💻 CPP
📖 第 1 页 / 共 2 页
字号:
        int l = fi->readx(ibuf, UPX_MIN(rest, (off_t)blocksize));        if (l == 0) {            break;        }        rest -= l;        // Note: compression for a block can fail if the        //       file is e.g. blocksize + 1 bytes long        // compress        ph.c_len = ph.u_len = l;        ph.overlap_overhead = 0;        unsigned end_u_adler = 0;        if (ft) {            // compressWithFilters() updates u_adler _inside_ compress();            // that is, AFTER filtering.  We want BEFORE filtering,            // so that decompression checks the end-to-end checksum.            end_u_adler = upx_adler32(ibuf, ph.u_len, ph.u_adler);            ft->buf_len = l;                // compressWithFilters() requirements?            ph.filter = 0;            ph.filter_cto = 0;            ft->id = 0;            ft->cto = 0;            compressWithFilters(ft, OVERHEAD, NULL_cconf, filter_strategy,                                0, 0, 0, hdr_ibuf, hdr_u_len);        }        else {            (void) compress(ibuf, ph.u_len, obuf);    // ignore return value        }        if (ph.c_len < ph.u_len) {            const upx_bytep tbuf = NULL;            if (ft == NULL || ft->id == 0) tbuf = ibuf;            ph.overlap_overhead = OVERHEAD;            if (!testOverlappingDecompression(obuf, tbuf, ph.overlap_overhead)) {                // not in-place compressible                ph.c_len = ph.u_len;            }        }        if (ph.c_len >= ph.u_len) {            // block is not compressible            ph.c_len = ph.u_len;            memcpy(obuf, ibuf, ph.c_len);            // must update checksum of compressed data            ph.c_adler = upx_adler32(ibuf, ph.u_len, ph.saved_c_adler);        }        // write block sizes        b_info tmp;        if (hdr_u_len) {            unsigned hdr_c_len = 0;            MemBuffer hdr_obuf;            hdr_obuf.allocForCompression(hdr_u_len);            int r = upx_compress(hdr_ibuf, hdr_u_len, hdr_obuf, &hdr_c_len, 0,                ph.method, 10, NULL, NULL);            if (r != UPX_E_OK)                throwInternalError("header compression failed");            if (hdr_c_len >= hdr_u_len)                throwInternalError("header compression size increase");            ph.saved_u_adler = upx_adler32(hdr_ibuf, hdr_u_len, init_u_adler);            ph.saved_c_adler = upx_adler32(hdr_obuf, hdr_c_len, init_c_adler);            ph.u_adler = upx_adler32(ibuf, ph.u_len, ph.saved_u_adler);            ph.c_adler = upx_adler32(obuf, ph.c_len, ph.saved_c_adler);            end_u_adler = ph.u_adler;            memset(&tmp, 0, sizeof(tmp));            set_native32(&tmp.sz_unc, hdr_u_len);            set_native32(&tmp.sz_cpr, hdr_c_len);            tmp.b_method = (unsigned char) ph.method;            fo->write(&tmp, sizeof(tmp));            b_len += sizeof(b_info);            fo->write(hdr_obuf, hdr_c_len);            total_out += hdr_c_len;            total_in  += hdr_u_len;            hdr_u_len = 0;  // compress hdr one time only        }        memset(&tmp, 0, sizeof(tmp));        set_native32(&tmp.sz_unc, ph.u_len);        set_native32(&tmp.sz_cpr, ph.c_len);        if (ph.c_len < ph.u_len) {            tmp.b_method = (unsigned char) ph.method;            if (ft) {                tmp.b_ftid = (unsigned char) ft->id;                tmp.b_cto8 = ft->cto;            }        }        fo->write(&tmp, sizeof(tmp));        b_len += sizeof(b_info);        // write compressed data        if (ph.c_len < ph.u_len) {            fo->write(obuf, ph.c_len);            // Checks ph.u_adler after decompression, after unfiltering            verifyOverlappingDecompression(ft);        }        else {            fo->write(ibuf, ph.u_len);        }        if (ft) {            ph.u_adler = end_u_adler;        }        total_in += ph.u_len;        total_out += ph.c_len;    }}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){    b_info hdr; memset(&hdr, 0, sizeof(hdr));    while (wanted) {        fi->readx(&hdr, szb_info);        int const sz_unc = ph.u_len = get_native32(&hdr.sz_unc);        int const sz_cpr = ph.c_len = get_native32(&hdr.sz_cpr);        ph.filter_cto = hdr.b_cto8;        if (sz_unc == 0) { // must never happen while 0!=wanted            throwCompressedDataViolation();            break;        }        if (sz_unc <= 0 || sz_cpr <= 0)            throwCompressedDataViolation();        if (sz_cpr > sz_unc || sz_unc > (int)blocksize)            throwCompressedDataViolation();        int j = blocksize + OVERHEAD - sz_cpr;        fi->readx(ibuf+j, sz_cpr);        // update checksum of compressed data        c_adler = upx_adler32(ibuf + j, sz_cpr, c_adler);        // decompress        if (sz_cpr < sz_unc)        {            decompress(ibuf+j, ibuf, false);            if (12==szb_info) { // modern per-block filter                if (hdr.b_ftid) {                    Filter ft(ph.level);  // FIXME: ph.level for b_info?                    ft.init(hdr.b_ftid, 0);                    ft.cto = hdr.b_cto8;                    ft.unfilter(ibuf, sz_unc);                }            }            else { // ancient per-file filter                if (first_PF_X) { // Elf32_Ehdr is never filtered                    first_PF_X = false;  // but everything else might be                }                else if (ph.filter) {                    Filter ft(ph.level);                    ft.init(ph.filter, 0);                    ft.cto = (unsigned char) ph.filter_cto;                    ft.unfilter(ibuf, sz_unc);                }            }            j = 0;        }        // update checksum of uncompressed data        u_adler = upx_adler32(ibuf + j, sz_unc, u_adler);        total_in  += sz_cpr;        total_out += sz_unc;        // write block        if (fo)            fo->write(ibuf + j, sz_unc);        wanted -= sz_unc;    }}/*************************************************************************// Generic Unix canUnpack().**************************************************************************/int PackUnix::canUnpack(){    upx_byte buf[128];    const int bufsize = sizeof(buf);    fi->seek(-bufsize, SEEK_END);    fi->readx(buf, bufsize);    if (!getPackHeader(buf, bufsize, true))  // allow incompressible extents        return false;    int l = ph.buf_offset + ph.getPackHeaderSize();    if (l < 0 || l + 4 > bufsize)        throwCantUnpack("file corrupted");    overlay_offset = get_native32(buf+l);    if ((off_t)overlay_offset >= file_size)        throwCantUnpack("file corrupted");    return true;}/*************************************************************************// Generic Unix unpack().//// This code looks much like the one in stub/l_linux.c// See notes there.**************************************************************************/void PackUnix::unpack(OutputFile *fo){    unsigned szb_info = sizeof(b_info);    {        Elf32_Ehdr ehdr;        fi->seek(0, SEEK_SET);        fi->readx(&ehdr, sizeof(ehdr));        unsigned const e_entry = get_native32(&ehdr.e_entry);        if (e_entry < 0x401180) { /* old style, 8-byte b_info */            szb_info = 2*sizeof(unsigned);        }        else {            Elf32_Phdr phdr;            fi->seek(get_native32(&ehdr.e_phoff), SEEK_SET);            fi->readx(&phdr, sizeof(phdr));            unsigned const p_vaddr = get_native32(&phdr.p_vaddr);            if (0x80==(e_entry - p_vaddr)) { /* 1.22 old style */                szb_info = 2*sizeof(unsigned);            }        }    }    unsigned c_adler = upx_adler32(NULL, 0);    unsigned u_adler = upx_adler32(NULL, 0);    // defaults for ph.version == 8    unsigned orig_file_size = 0;    blocksize = 512 * 1024;    fi->seek(overlay_offset, SEEK_SET);    if (ph.version > 8)    {        p_info hbuf;        fi->readx(&hbuf, sizeof(hbuf));        orig_file_size = get_native32(&hbuf.p_filesize);        blocksize = get_native32(&hbuf.p_blocksize);        if (file_size > (off_t)orig_file_size || blocksize > orig_file_size)            throwCantUnpack("file header corrupted");    }    else    {        // skip 4 bytes (program id)        fi->seek(4, SEEK_CUR);    }    ibuf.alloc(blocksize + OVERHEAD);    // decompress blocks    unsigned total_in = 0;    unsigned total_out = 0;    b_info bhdr; memset(&bhdr, 0, sizeof(bhdr));    for (;;)    {#define buf ibuf        int i;        unsigned sz_unc, sz_cpr;        fi->readx(&bhdr, szb_info);        ph.u_len = sz_unc = get_native32(&bhdr.sz_unc);        ph.c_len = sz_cpr = get_native32(&bhdr.sz_cpr);        if (sz_unc == 0)                   // uncompressed size 0 -> EOF        {            // note: must reload sz_cpr as magic is always stored le32            sz_cpr = get_le32(&bhdr.sz_cpr);            if (sz_cpr != UPX_MAGIC_LE32)  // sz_cpr must be h->magic                throwCompressedDataViolation();            break;        }        if (sz_unc <= 0 || sz_cpr <= 0)            throwCompressedDataViolation();        if (sz_cpr > sz_unc || sz_unc > blocksize)            throwCompressedDataViolation();        i = blocksize + OVERHEAD - sz_cpr;        fi->readx(buf+i, sz_cpr);        // update checksum of compressed data        c_adler = upx_adler32(buf + i, sz_cpr, c_adler);        // decompress        if (sz_cpr < sz_unc) {            decompress(buf+i, buf, false);            if (0!=bhdr.b_ftid) {                Filter ft(ph.level);                ft.init(bhdr.b_ftid);                ft.cto = bhdr.b_cto8;                ft.unfilter(buf, sz_unc);            }            i = 0;        }        // update checksum of uncompressed data        u_adler = upx_adler32(buf + i, sz_unc, u_adler);        total_in  += sz_cpr;        total_out += sz_unc;        // write block        if (fo)            fo->write(buf + i, sz_unc);#undef buf    }    // update header with totals    ph.c_len = total_in;    ph.u_len = total_out;    // all bytes must be written    if (ph.version > 8 && total_out != orig_file_size)        throwEOFException();    // finally test the checksums    if (ph.c_adler != c_adler || ph.u_adler != u_adler)        throwChecksumError();}/*vi:ts=4:et*/

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -