1 /* packer.cpp --
2 
3    This file is part of the UPX executable compressor.
4 
5    Copyright (C) 1996-2020 Markus Franz Xaver Johannes Oberhumer
6    Copyright (C) 1996-2020 Laszlo Molnar
7    All Rights Reserved.
8 
9    UPX and the UCL library are free software; you can redistribute them
10    and/or modify them under the terms of the GNU General Public License as
11    published by the Free Software Foundation; either version 2 of
12    the License, or (at your option) any later version.
13 
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License for more details.
18 
19    You should have received a copy of the GNU General Public License
20    along with this program; see the file COPYING.
21    If not, write to the Free Software Foundation, Inc.,
22    59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23 
24    Markus F.X.J. Oberhumer              Laszlo Molnar
25    <markus@oberhumer.com>               <ezerotven+github@gmail.com>
26  */
27 
28 
29 #include "conf.h"
30 #include "file.h"
31 #include "packer.h"
32 #include "filter.h"
33 #include "linker.h"
34 #include "ui.h"
35 
36 
37 /*************************************************************************
38 //
39 **************************************************************************/
40 
Packer(InputFile * f)41 Packer::Packer(InputFile *f) :
42     bele(NULL),
43     fi(f), file_size(-1), ph_format(-1), ph_version(-1),
44     uip(NULL), linker(NULL),
45     last_patch(NULL), last_patch_len(0), last_patch_off(0)
46 {
47     if (fi != NULL)
48         file_size = fi->st_size();
49     uip = new UiPacker(this);
50     mem_clear(&ph, sizeof(ph));
51 }
52 
53 
~Packer()54 Packer::~Packer()
55 {
56     delete uip; uip = NULL;
57     delete linker; linker = NULL;
58 }
59 
60 
61 // for PackMaster
assertPacker() const62 void Packer::assertPacker() const
63 {
64     assert(getFormat() > 0);
65     assert(getFormat() < 255);
66     assert(getVersion() >= 11);
67     assert(getVersion() <= 14);
68     assert(strlen(getName()) <= 15);
69     // info: 36 is the limit for show_all_packers() in help.cpp
70     assert(strlen(getFullName(opt)) <= 32);
71     assert(strlen(getFullName(NULL)) <= 32);
72     if (bele == NULL) fprintf(stderr, "%s\n", getName());
73     assert(bele != NULL);
74     if (getFormat() != UPX_F_MACH_FAT) // macho/fat is multiarch
75     {
76         const N_BELE_RTP::AbstractPolicy *format_bele;
77         if (getFormat() < 128)
78             format_bele = &N_BELE_RTP::le_policy;
79         else
80             format_bele = &N_BELE_RTP::be_policy;
81         if (bele != format_bele) fprintf(stderr, "%s\n", getName());
82         assert(bele == format_bele);
83     }
84 #if 1
85     Linker *l = newLinker();
86     if (bele != l->bele) fprintf(stderr, "%s\n", getName());
87     assert(bele == l->bele);
88     delete l;
89 #endif
90 }
91 
92 
93 /*************************************************************************
94 // public entries called from class PackMaster
95 **************************************************************************/
96 
doPack(OutputFile * fo)97 void Packer::doPack(OutputFile *fo)
98 {
99     uip->uiPackStart(fo);
100     pack(fo);
101     uip->uiPackEnd(fo);
102 }
103 
doUnpack(OutputFile * fo)104 void Packer::doUnpack(OutputFile *fo)
105 {
106     uip->uiUnpackStart(fo);
107     unpack(fo);
108     uip->uiUnpackEnd(fo);
109 }
110 
doTest()111 void Packer::doTest()
112 {
113     uip->uiTestStart();
114     test();
115     uip->uiTestEnd();
116 }
117 
doList()118 void Packer::doList()
119 {
120     uip->uiListStart();
121     list();
122     uip->uiListEnd();
123 }
124 
doFileInfo()125 void Packer::doFileInfo()
126 {
127     uip->uiFileInfoStart();
128     fileInfo();
129     uip->uiFileInfoEnd();
130 }
131 
132 
133 /*************************************************************************
134 // default actions
135 **************************************************************************/
136 
test()137 void Packer::test()
138 {
139     unpack(NULL);
140 }
141 
142 
list()143 void Packer::list()
144 {
145     uip->uiList();
146 }
147 
148 
fileInfo()149 void Packer::fileInfo()
150 {
151     // FIXME: subclasses should list their sections here
152     // We also should try to get a nice layout...
153 }
154 
155 
testUnpackVersion(int version) const156 bool Packer::testUnpackVersion(int version) const
157 {
158     if (version != ph_version && ph_version != -1)
159         throwCantUnpack("program has been modified; run a virus checker!");
160     if (!canUnpackVersion(version))
161         throwCantUnpack("I am not compatible with older versions of UPX");
162     return true;
163 }
164 
165 
testUnpackFormat(int format) const166 bool Packer::testUnpackFormat(int format) const
167 {
168     if (format != ph_format && ph_format != -1)
169         throwCantUnpack("program has been modified; run a virus checker!");
170     return canUnpackFormat(format);
171 }
172 
173 
ph_skipVerify(const PackHeader & ph)174 bool ph_skipVerify(const PackHeader &ph)
175 {
176     if (M_IS_DEFLATE(ph.method))
177         return false;
178     if (M_IS_LZMA(ph.method))
179         return false;
180     if (ph.level > 1)
181         return false;
182     return true;
183 }
184 
185 
186 /*************************************************************************
187 // compress - wrap call to low-level upx_compress()
188 **************************************************************************/
189 
compress(upx_bytep i_ptr,unsigned i_len,upx_bytep o_ptr,const upx_compress_config_t * cconf_parm)190 bool Packer::compress(upx_bytep i_ptr, unsigned i_len, upx_bytep o_ptr,
191                       const upx_compress_config_t *cconf_parm)
192 {
193     ph.u_len = i_len;
194     ph.c_len = 0;
195     assert(ph.level >= 1); assert(ph.level <= 10);
196 
197     // Avoid too many progress bar updates. 64 is s->bar_len in ui.cpp.
198     unsigned step = (ph.u_len < 64*1024) ? 0 : ph.u_len / 64;
199 
200     // save current checksums
201     ph.saved_u_adler = ph.u_adler;
202     ph.saved_c_adler = ph.c_adler;
203     // update checksum of uncompressed data
204     ph.u_adler = upx_adler32(i_ptr, ph.u_len, ph.u_adler);
205 
206     // set compression parameters
207     upx_compress_config_t cconf; cconf.reset();
208     if (cconf_parm)
209         cconf = *cconf_parm;
210     // cconf options
211     if (M_IS_NRV2B(ph.method) || M_IS_NRV2D(ph.method) || M_IS_NRV2E(ph.method))
212     {
213         if (opt->crp.crp_ucl.c_flags != -1)
214             cconf.conf_ucl.c_flags = opt->crp.crp_ucl.c_flags;
215         if (opt->crp.crp_ucl.p_level != -1)
216             cconf.conf_ucl.p_level = opt->crp.crp_ucl.p_level;
217         if (opt->crp.crp_ucl.h_level != -1)
218             cconf.conf_ucl.h_level = opt->crp.crp_ucl.h_level;
219         if (opt->crp.crp_ucl.max_offset != UINT_MAX && opt->crp.crp_ucl.max_offset < cconf.conf_ucl.max_offset)
220             cconf.conf_ucl.max_offset = opt->crp.crp_ucl.max_offset;
221         if (opt->crp.crp_ucl.max_match != UINT_MAX && opt->crp.crp_ucl.max_match < cconf.conf_ucl.max_match)
222             cconf.conf_ucl.max_match = opt->crp.crp_ucl.max_match;
223 #if (WITH_NRV)
224         if (ph.level >= 7 || (ph.level >= 4 && ph.u_len >= 512*1024))
225             step = 0;
226 #endif
227     }
228     if (M_IS_LZMA(ph.method))
229     {
230         oassign(cconf.conf_lzma.pos_bits, opt->crp.crp_lzma.pos_bits);
231         oassign(cconf.conf_lzma.lit_pos_bits, opt->crp.crp_lzma.lit_pos_bits);
232         oassign(cconf.conf_lzma.lit_context_bits, opt->crp.crp_lzma.lit_context_bits);
233         oassign(cconf.conf_lzma.dict_size, opt->crp.crp_lzma.dict_size);
234         oassign(cconf.conf_lzma.num_fast_bytes, opt->crp.crp_lzma.num_fast_bytes);
235     }
236     if (M_IS_DEFLATE(ph.method))
237     {
238         oassign(cconf.conf_zlib.mem_level, opt->crp.crp_zlib.mem_level);
239         oassign(cconf.conf_zlib.window_bits, opt->crp.crp_zlib.window_bits);
240         oassign(cconf.conf_zlib.strategy, opt->crp.crp_zlib.strategy);
241     }
242     if (uip->ui_pass >= 0)
243         uip->ui_pass++;
244     uip->startCallback(ph.u_len, step, uip->ui_pass, uip->ui_total_passes);
245     uip->firstCallback();
246 
247     //OutputFile::dump("data.raw", in, ph.u_len);
248 
249     // compress
250     int r = upx_compress(i_ptr, ph.u_len, o_ptr, &ph.c_len,
251                          uip->getCallback(),
252                          ph.method, ph.level, &cconf, &ph.compress_result);
253 
254     //uip->finalCallback(ph.u_len, ph.c_len);
255     uip->endCallback();
256 
257     if (r == UPX_E_OUT_OF_MEMORY)
258         throwOutOfMemoryException();
259     if (r != UPX_E_OK)
260         throwInternalError("compression failed");
261 
262     if (M_IS_NRV2B(ph.method) || M_IS_NRV2D(ph.method) || M_IS_NRV2E(ph.method))
263     {
264         const ucl_uint *res = ph.compress_result.result_ucl.result;
265         //ph.min_offset_found = res[0];
266         ph.max_offset_found = res[1];
267         //ph.min_match_found = res[2];
268         ph.max_match_found = res[3];
269         //ph.min_run_found = res[4];
270         ph.max_run_found = res[5];
271         ph.first_offset_found = res[6];
272         //ph.same_match_offsets_found = res[7];
273         if (cconf_parm)
274         {
275             assert(cconf.conf_ucl.max_offset == 0 || cconf.conf_ucl.max_offset >= ph.max_offset_found);
276             assert(cconf.conf_ucl.max_match == 0 || cconf.conf_ucl.max_match >= ph.max_match_found);
277         }
278     }
279 
280     //printf("\nPacker::compress: %d/%d: %7d -> %7d\n", ph.method, ph.level, ph.u_len, ph.c_len);
281     if (!checkCompressionRatio(ph.u_len, ph.c_len))
282         return false;
283     // return in any case if not compressible
284     if (ph.c_len >= ph.u_len)
285         return false;
286 
287     // update checksum of compressed data
288     ph.c_adler = upx_adler32(o_ptr, ph.c_len, ph.c_adler);
289     // Decompress and verify. Skip this when using the fastest level.
290     if (!ph_skipVerify(ph))
291     {
292         // decompress
293         unsigned new_len = ph.u_len;
294         r = upx_decompress(o_ptr, ph.c_len, i_ptr, &new_len, ph.method, &ph.compress_result);
295         if (r == UPX_E_OUT_OF_MEMORY)
296             throwOutOfMemoryException();
297         //printf("%d %d: %d %d %d\n", ph.method, r, ph.c_len, ph.u_len, new_len);
298         if (r != UPX_E_OK)
299             throwInternalError("decompression failed");
300         if (new_len != ph.u_len)
301             throwInternalError("decompression failed (size error)");
302 
303         // verify decompression
304         if (ph.u_adler != upx_adler32(i_ptr, ph.u_len, ph.saved_u_adler))
305             throwInternalError("decompression failed (checksum error)");
306     }
307     return true;
308 }
309 
310 
311 #if 0
312 bool Packer::compress(upx_bytep in, upx_bytep out,
313                       const upx_compress_config_t *cconf)
314 {
315     return ph_compress(ph, in, out, cconf);
316 }
317 #endif
318 
319 
checkDefaultCompressionRatio(unsigned u_len,unsigned c_len) const320 bool Packer::checkDefaultCompressionRatio(unsigned u_len, unsigned c_len) const
321 {
322     assert((int)u_len > 0);
323     assert((int)c_len > 0);
324     if (c_len >= u_len)
325         return false;
326     unsigned gain = u_len - c_len;
327 
328     if (gain < 512)             // need at least 512 bytes gain
329         return false;
330 #if 1
331     if (gain >= 4096)           // ok if we have 4096 bytes gain
332         return true;
333     if (gain >= u_len / 16)     // ok if we have 6.25% gain
334         return true;
335     return false;
336 #else
337     return true;
338 #endif
339 }
340 
341 
checkCompressionRatio(unsigned u_len,unsigned c_len) const342 bool Packer::checkCompressionRatio(unsigned u_len, unsigned c_len) const
343 {
344     return checkDefaultCompressionRatio(u_len, c_len);
345 }
346 
checkFinalCompressionRatio(const OutputFile * fo) const347 bool Packer::checkFinalCompressionRatio(const OutputFile *fo) const
348 {
349     const unsigned u_len = file_size;
350     const unsigned c_len = fo->getBytesWritten();
351     return checkDefaultCompressionRatio(u_len, c_len);
352 }
353 
354 
355 /*************************************************************************
356 // decompress
357 **************************************************************************/
358 
ph_decompress(PackHeader & ph,const upx_bytep in,upx_bytep out,bool verify_checksum,Filter * ft)359 void ph_decompress(PackHeader &ph, const upx_bytep in, upx_bytep out,
360                    bool verify_checksum, Filter *ft)
361 {
362     unsigned adler;
363 
364     // verify checksum of compressed data
365     if (verify_checksum)
366     {
367         adler = upx_adler32(in, ph.c_len, ph.saved_c_adler);
368         if (adler != ph.c_adler)
369             throwChecksumError();
370     }
371 
372     // decompress
373     if (ph.u_len < ph.c_len) {
374         throwCantUnpack("header corrupted");
375     }
376     unsigned new_len = ph.u_len;
377     int r = upx_decompress(in, ph.c_len, out, &new_len, ph.method, &ph.compress_result);
378     if (r == UPX_E_OUT_OF_MEMORY)
379         throwOutOfMemoryException();
380     if (r != UPX_E_OK || new_len != ph.u_len)
381         throwCompressedDataViolation();
382 
383     // verify checksum of decompressed data
384     if (verify_checksum)
385     {
386         if (ft)
387             ft->unfilter(out, ph.u_len);
388         adler = upx_adler32(out, ph.u_len, ph.saved_u_adler);
389         if (adler != ph.u_adler)
390             throwChecksumError();
391     }
392 }
393 
394 
decompress(const upx_bytep in,upx_bytep out,bool verify_checksum,Filter * ft)395 void Packer::decompress(const upx_bytep in, upx_bytep out,
396                         bool verify_checksum, Filter *ft)
397 {
398     ph_decompress(ph, in, out, verify_checksum, ft);
399 }
400 
401 
402 /*************************************************************************
403 // overlapping decompression
404 **************************************************************************/
405 
406 static
ph_testOverlappingDecompression(const PackHeader & ph,const upx_bytep buf,const upx_bytep tbuf,unsigned overlap_overhead)407 bool ph_testOverlappingDecompression(const PackHeader &ph,
408                                      const upx_bytep buf,
409                                      const upx_bytep tbuf,
410                                      unsigned overlap_overhead)
411 {
412     if (ph.c_len >= ph.u_len)
413         return false;
414 
415     assert((int) overlap_overhead >= 0);
416     assert((int) (ph.u_len + overlap_overhead) >= 0);
417 
418     // Because upx_test_overlap() does not use the asm_fast decompressor
419     // we must account for extra 3 bytes that asm_fast does use,
420     // or else we may fail at runtime decompression.
421     unsigned extra = 0;
422     if (M_IS_NRV2B(ph.method) || M_IS_NRV2D(ph.method) || M_IS_NRV2E(ph.method))
423         extra = 3;
424     if (overlap_overhead <= 4 + extra)  // don't waste time here
425         return false;
426     overlap_overhead -= extra;
427 
428     unsigned src_off = ph.u_len + overlap_overhead - ph.c_len;
429     unsigned new_len = ph.u_len;
430     int r = upx_test_overlap(buf - src_off, tbuf,
431                              src_off, ph.c_len, &new_len,
432                              ph.method, &ph.compress_result);
433     if (r == UPX_E_OUT_OF_MEMORY)
434         throwOutOfMemoryException();
435     return (r == UPX_E_OK && new_len == ph.u_len);
436 }
437 
438 
testOverlappingDecompression(const upx_bytep buf,const upx_bytep tbuf,unsigned overlap_overhead) const439 bool Packer::testOverlappingDecompression(const upx_bytep buf, const upx_bytep tbuf,
440                                           unsigned overlap_overhead) const
441 {
442     return ph_testOverlappingDecompression(ph, buf, tbuf, overlap_overhead);
443 }
444 
445 
verifyOverlappingDecompression(Filter * ft)446 void Packer::verifyOverlappingDecompression(Filter *ft)
447 {
448     assert(ph.c_len < ph.u_len);
449     assert((int)ph.overlap_overhead > 0);
450     // Idea:
451     //   obuf[] was allocated with MemBuffer::allocForCompression(), and
452     //   its contents are no longer needed, i.e. the compressed data
453     //   must have been already written.
454     //   We now can perform a real overlapping decompression and
455     //   verify the checksum.
456     //
457     // Note:
458     //   This verify is just because of complete paranoia that there
459     //   could be a hidden bug in the upx_test_overlap implementation,
460     //   and it should not be necessary at all.
461     //
462     // See also:
463     //   Filter::verifyUnfilter()
464 
465     if (ph_skipVerify(ph))
466         return;
467     unsigned offset = (ph.u_len + ph.overlap_overhead) - ph.c_len;
468     if (offset + ph.c_len > obuf.getSize())
469         return;
470     memmove(obuf + offset, obuf, ph.c_len);
471     decompress(obuf + offset, obuf, true, ft);
472     obuf.checkState();
473 }
474 
475 
verifyOverlappingDecompression(upx_bytep o_ptr,unsigned o_size,Filter * ft)476 void Packer::verifyOverlappingDecompression(upx_bytep o_ptr, unsigned o_size, Filter *ft)
477 {
478     assert(ph.c_len < ph.u_len);
479     assert((int)ph.overlap_overhead > 0);
480     if (ph_skipVerify(ph))
481         return;
482     unsigned offset = (ph.u_len + ph.overlap_overhead) - ph.c_len;
483     if (offset + ph.c_len > o_size)
484         return;
485     memmove(o_ptr + offset, o_ptr, ph.c_len);
486     decompress(o_ptr + offset, o_ptr, true, ft);
487 }
488 
489 
490 /*************************************************************************
491 // Find overhead for in-place decompression in a heuristic way
492 // (using a binary search). Return 0 on error.
493 //
494 // To speed up things:
495 //   - you can pass the range of an acceptable interval (so that
496 //     we can succeed early)
497 //   - you can enforce an upper_limit (so that we can fail early)
498 **************************************************************************/
499 
findOverlapOverhead(const upx_bytep buf,const upx_bytep tbuf,unsigned range,unsigned upper_limit) const500 unsigned Packer::findOverlapOverhead(const upx_bytep buf,
501                                      const upx_bytep tbuf,
502                                      unsigned range,
503                                      unsigned upper_limit) const
504 {
505     assert((int) range >= 0);
506 
507     // prepare to deal with very pessimistic values
508     unsigned low = 1;
509     unsigned high = UPX_MIN(ph.u_len + 512, upper_limit);
510     // but be optimistic for first try (speedup)
511     unsigned m = UPX_MIN(16u, high);
512     //
513     unsigned overhead = 0;
514     unsigned nr = 0;          // statistics
515 
516     while (high >= low)
517     {
518         assert(m >= low); assert(m <= high);
519         assert(m < overhead || overhead == 0);
520         nr++;
521         bool success = testOverlappingDecompression(buf, tbuf, m);
522         //printf("testOverlapOverhead(%d): %d %d: %d -> %d\n", nr, low, high, m, (int)success);
523         if (success)
524         {
525             overhead = m;
526             // Succeed early if m lies in [low .. low+range-1], i.e. if
527             // if the range of the current interval is <= range.
528             //   if (m <= low + range - 1)
529             //   if (m <  low + range)
530             if (m - low < range)                    // avoid underflow
531                 break;
532             high = m - 1;
533         }
534         else
535             low = m + 1;
536         ////m = (low + high) / 2;
537         m = (low & high) + ((low ^ high) >> 1);     // avoid overflow
538     }
539 
540     //printf("findOverlapOverhead: %d (%d tries)\n", overhead, nr);
541     if (overhead == 0)
542         throwInternalError("this is an oo bug");
543 
544     UNUSED(nr);
545     return overhead;
546 }
547 
548 
549 /*************************************************************************
550 // file i/o utils
551 **************************************************************************/
552 
handleStub(InputFile * fif,OutputFile * fo,unsigned size)553 void Packer::handleStub(InputFile *fif, OutputFile *fo, unsigned size)
554 {
555     if (fo)
556     {
557         if (size > 0)
558         {
559             // copy stub from exe
560             info("Copying original stub: %u bytes", size);
561             ByteArray(stub, size);
562             fif->seek(0,SEEK_SET);
563             fif->readx(stub,size);
564             fo->write(stub,size);
565         }
566         else
567         {
568             // no stub
569         }
570     }
571 }
572 
573 
checkOverlay(unsigned overlay)574 void Packer::checkOverlay(unsigned overlay)
575 {
576     if ((int)overlay < 0 || (off_t)overlay > file_size)
577         throw OverlayException("invalid overlay size; file is possibly corrupt");
578     if (overlay == 0)
579         return;
580     info("Found overlay: %d bytes", overlay);
581     if (opt->overlay == opt->SKIP_OVERLAY)
582         throw OverlayException("file has overlay -- skipped; try '--overlay=copy'");
583 }
584 
585 
copyOverlay(OutputFile * fo,unsigned overlay,MemBuffer * buf,bool do_seek)586 void Packer::copyOverlay(OutputFile *fo, unsigned overlay,
587                          MemBuffer *buf,
588                          bool do_seek)
589 {
590     assert((int)overlay >= 0);
591     assert((off_t)overlay < file_size);
592     buf->checkState();
593     if (!fo || overlay == 0)
594         return;
595     if (opt->overlay != opt->COPY_OVERLAY)
596     {
597         assert(opt->overlay == opt->STRIP_OVERLAY);
598         infoWarning("stripping overlay: %d bytes", overlay);
599         return;
600     }
601     info("Copying overlay: %d bytes", overlay);
602     if (do_seek)
603         fi->seek(-(off_t)overlay, SEEK_END);
604 
605     // get buffer size, align to improve i/o speed
606     unsigned buf_size = buf->getSize();
607     if (buf_size > 65536)
608         buf_size = ALIGN_DOWN(buf_size, 4096u);
609     assert((int)buf_size > 0);
610 
611     do {
612         unsigned len = overlay < buf_size ? overlay : buf_size;
613         fi->readx(buf, len);
614         fo->write(buf, len);
615         overlay -= len;
616     } while (overlay > 0);
617     buf->checkState();
618 }
619 
620 
621 // Create a pseudo-unique program id.
getRandomId() const622 unsigned Packer::getRandomId() const
623 {
624     if (opt->debug.disable_random_id)
625         return 0x01020304;
626     unsigned id = 0;
627 #if 0 && defined(__unix__)
628     // Don't consume precious bytes from /dev/urandom.
629     int fd = open("/dev/urandom", O_RDONLY | O_BINARY);
630     if (fd < 0)
631         fd = open("/dev/random", O_RDONLY | O_BINARY);
632     if (fd >= 0)
633     {
634         if (read(fd, &id, 4) != 4)
635             id = 0;
636         close(fd);
637     }
638 #endif
639     while (id == 0)
640     {
641 #if !(HAVE_GETTIMEOFDAY) || ((ACC_OS_DOS32) && defined(__DJGPP__))
642         id ^= (unsigned) time(NULL);
643         id ^= ((unsigned) clock()) << 12;
644 #else
645         struct timeval tv;
646         gettimeofday(&tv, 0);
647         id ^= (unsigned) tv.tv_sec;
648         id ^= ((unsigned) tv.tv_usec) << 12;  // shift into high-bits
649 #endif
650 #if (HAVE_GETPID)
651         id ^= (unsigned) getpid();
652 #endif
653         id ^= (unsigned) fi->st.st_ino;
654         id ^= (unsigned) fi->st.st_atime;
655         id ^= (unsigned) rand();
656     }
657     return id;
658 }
659 
660 
661 /*************************************************************************
662 // packheader util
663 **************************************************************************/
664 
665 // this is called directly after the constructor from class PackMaster
initPackHeader()666 void Packer::initPackHeader()
667 {
668     mem_clear(&ph, sizeof(ph));
669     ph.version = getVersion();
670     ph.format = getFormat();
671     ph.method = M_NONE;
672     ph.level = -1;
673     ph.u_adler = ph.c_adler = ph.saved_u_adler = ph.saved_c_adler = upx_adler32(NULL,0);
674     ph.buf_offset = 0;
675     ph.u_file_size = file_size;
676 }
677 
678 
679 // this is called directly after canPack() from class PackMaster
updatePackHeader()680 void Packer::updatePackHeader()
681 {
682     assert(opt->cmd == CMD_COMPRESS);
683     //
684     const int *m = getCompressionMethods(opt->method, opt->level);
685     ph.method = m[0];
686     ph.level = opt->level;
687     if (ph.level < 0)
688         ph.level = file_size < 512*1024 ? 8 : 7;
689     //
690     assert(isValidCompressionMethod(ph.method));
691     assert(1 <= ph.level && ph.level <= 10);
692 }
693 
694 
695 // FIXME: remove patchPackHeader() and fold into relocateLoader();
696 //   then make linker->relocate() private (friend Packer)
patchPackHeader(void * b,int blen)697 int Packer::patchPackHeader(void *b, int blen)
698 {
699     assert(isValidFilter(ph.filter));
700 
701     const int size = ph.getPackHeaderSize();
702     if (linker->findSection("UPX1HEAD", false))
703         assert(size == linker->getSectionSize("UPX1HEAD"));
704     int boff = find_le32(b, blen, UPX_MAGIC_LE32);
705     checkPatch(b, blen, boff, size);
706 
707     unsigned char *p = (unsigned char *)b + boff;
708     ph.putPackHeader(p);
709 
710     return boff;
711 }
712 
713 
getPackHeader(void * b,int blen,bool allow_incompressible)714 bool Packer::getPackHeader(void *b, int blen, bool allow_incompressible)
715 {
716     if (!ph.fillPackHeader((unsigned char *)b, blen))
717         return false;
718 
719     if (ph.version > getVersion())
720         throwCantUnpack("need a newer version of UPX");
721     // Some formats might be able to unpack old versions because
722     // their implementation hasn't changed. Ask them.
723     if (opt->cmd != CMD_FILEINFO)
724         if (!testUnpackVersion(ph.version))
725             return false;
726 
727     if (ph.c_len > ph.u_len
728         || (ph.c_len == ph.u_len && !allow_incompressible)
729         || (off_t)ph.c_len >= file_size
730         || ph.version <= 0 || ph.version >= 0xff)
731         throwCantUnpack("header corrupted");
732     else if ((off_t)ph.u_len > ph.u_file_size)
733     {
734 #if 0
735         // FIXME: does this check make sense w.r.t. overlays ???
736         if (ph.format == UPX_F_WIN32_PE || ph.format == UPX_F_DOS_EXE)
737             // may get longer
738             ((void)0);
739         else
740             throwCantUnpack("header size corrupted");
741 #endif
742     }
743     if (!isValidCompressionMethod(ph.method))
744         throwCantUnpack("unknown compression method (try a newer version of UPX)");
745 
746     // Some formats might be able to unpack "subformats". Ask them.
747     if (!testUnpackFormat(ph.format))
748         return false;
749 
750     return true;
751 }
752 
753 
readPackHeader(int len,bool allow_incompressible)754 bool Packer::readPackHeader(int len, bool allow_incompressible)
755 {
756     assert((int)len > 0);
757     MemBuffer buf(len);
758     len = fi->read(buf, len);
759     if (len <= 0)
760         return false;
761     return getPackHeader(buf, len, allow_incompressible);
762 }
763 
764 
checkAlreadyPacked(const void * b,int blen)765 void Packer::checkAlreadyPacked(const void *b, int blen)
766 {
767     int boff = find_le32(b, blen, UPX_MAGIC_LE32);
768     if (boff < 0)
769         return;
770 
771     // FIXME: could add some more checks to verify that this
772     //   is a real PackHeader, e.g.
773     //
774     //PackHeader tmp;
775     //if (!tmp.fillPackHeader((unsigned char *)b + boff, blen - boff))
776     //    return;
777     //
778     // This also would require that the buffer in 'b' holds
779     // the full PackHeader, and not only the 4 magic bytes.
780 
781     throwAlreadyPacked();
782 }
783 
784 
785 /*************************************************************************
786 // patch util for loader
787 **************************************************************************/
788 
checkPatch(void * b,int blen,int boff,int size)789 void Packer::checkPatch(void *b, int blen, int boff, int size)
790 {
791     if (b == NULL && blen == 0 && boff == 0 && size == 0)
792     {
793         // reset
794         last_patch = NULL;
795         last_patch_len = 0;
796         last_patch_off = 0;
797         return;
798     }
799     if (b == NULL || blen <= 0 || boff < 0 || size <= 0)
800         throwBadLoader();
801     if (boff + size <= 0 || boff + size > blen)
802         throwBadLoader();
803     //printf("checkPatch: %p %5d %5d %2d\n", b, blen, boff, size);
804     if (b == last_patch)
805     {
806         if (boff + size > last_patch_off)
807             throwInternalError("invalid patch order");
808         // The next check is not strictly necessary, but the buffer
809         // length should better not increase...
810         if (blen > last_patch_len)
811             throwInternalError("invalid patch order (length)");
812     }
813     else
814         last_patch = b;
815     last_patch_len = blen;
816     last_patch_off = boff;
817 }
818 
819 
patch_be16(void * b,int blen,unsigned old,unsigned new_)820 int Packer::patch_be16(void *b, int blen, unsigned old, unsigned new_)
821 {
822     int boff = find_be16(b, blen, old);
823     checkPatch(b, blen, boff, 2);
824 
825     unsigned char *p = (unsigned char *)b + boff;
826     set_be16(p, new_);
827 
828     return boff;
829 }
830 
831 
patch_be16(void * b,int blen,const void * old,unsigned new_)832 int Packer::patch_be16(void *b, int blen, const void *old, unsigned new_)
833 {
834     int boff = find(b, blen, old, 2);
835     checkPatch(b, blen, boff, 2);
836 
837     unsigned char *p = (unsigned char *)b + boff;
838     set_be16(p, new_);
839 
840     return boff;
841 }
842 
843 
patch_be32(void * b,int blen,unsigned old,unsigned new_)844 int Packer::patch_be32(void *b, int blen, unsigned old, unsigned new_)
845 {
846     int boff = find_be32(b, blen, old);
847     checkPatch(b, blen, boff, 4);
848 
849     unsigned char *p = (unsigned char *)b + boff;
850     set_be32(p, new_);
851 
852     return boff;
853 }
854 
855 
patch_be32(void * b,int blen,const void * old,unsigned new_)856 int Packer::patch_be32(void *b, int blen, const void *old, unsigned new_)
857 {
858     int boff = find(b, blen, old, 4);
859     checkPatch(b, blen, boff, 4);
860 
861     unsigned char *p = (unsigned char *)b + boff;
862     set_be32(p, new_);
863 
864     return boff;
865 }
866 
867 
patch_le16(void * b,int blen,unsigned old,unsigned new_)868 int Packer::patch_le16(void *b, int blen, unsigned old, unsigned new_)
869 {
870     int boff = find_le16(b, blen, old);
871     checkPatch(b, blen, boff, 2);
872 
873     unsigned char *p = (unsigned char *)b + boff;
874     set_le16(p, new_);
875 
876     return boff;
877 }
878 
879 
patch_le16(void * b,int blen,const void * old,unsigned new_)880 int Packer::patch_le16(void *b, int blen, const void *old, unsigned new_)
881 {
882     int boff = find(b, blen, old, 2);
883     checkPatch(b, blen, boff, 2);
884 
885     unsigned char *p = (unsigned char *)b + boff;
886     set_le16(p, new_);
887 
888     return boff;
889 }
890 
891 
patch_le32(void * b,int blen,unsigned old,unsigned new_)892 int Packer::patch_le32(void *b, int blen, unsigned old, unsigned new_)
893 {
894     int boff = find_le32(b, blen, old);
895     checkPatch(b, blen, boff, 4);
896 
897     unsigned char *p = (unsigned char *)b + boff;
898     set_le32(p, new_);
899 
900     return boff;
901 }
902 
903 
patch_le32(void * b,int blen,const void * old,unsigned new_)904 int Packer::patch_le32(void *b, int blen, const void *old, unsigned new_)
905 {
906     int boff = find(b, blen, old, 4);
907     checkPatch(b, blen, boff, 4);
908 
909     unsigned char *p = (unsigned char *)b + boff;
910     set_le32(p, new_);
911 
912     return boff;
913 }
914 
915 
916 /*************************************************************************
917 // relocation util
918 **************************************************************************/
919 
optimizeReloc(upx_byte * in,unsigned relocnum,upx_byte * out,upx_byte * image,int bswap,int * big,int bits)920 upx_byte *Packer::optimizeReloc(upx_byte *in, unsigned relocnum,
921                                 upx_byte *out, upx_byte *image,
922                                 int bswap, int *big, int bits)
923 {
924     if (opt->exact)
925         throwCantPackExact();
926 
927     *big = 0;
928     if (relocnum == 0)
929         return out;
930     qsort(in,relocnum,4,le32_compare);
931 
932     unsigned jc,pc,oc;
933     upx_byte *fix = out;
934 
935     pc = (unsigned) -4;
936     for (jc = 0; jc<relocnum; jc++)
937     {
938         oc = get_le32(in+jc*4) - pc;
939         if (oc == 0)
940             continue;
941         else if ((int)oc < 4)
942             throwCantPack("overlapping fixups");
943         else if (oc < 0xF0)
944             *fix++ = (unsigned char) oc;
945         else if (oc < 0x100000)
946         {
947             *fix++ = (unsigned char) (0xF0+(oc>>16));
948             *fix++ = (unsigned char) oc;
949             *fix++ = (unsigned char) (oc>>8);
950         }
951         else
952         {
953             *big = 1;
954             *fix++ = 0xf0;
955             *fix++ = 0;
956             *fix++ = 0;
957             set_le32(fix,oc);
958             fix += 4;
959         }
960         pc += oc;
961         if (bswap)
962         {
963             if (bits == 32)
964                 acc_ua_swab32s(image + pc);
965             else if (bits == 64)
966                 set_be64(image + pc, get_le64(image + pc));
967             else
968                 throwInternalError("optimizeReloc problem");
969         }
970     }
971     *fix++ = 0;
972     return fix;
973 }
974 
optimizeReloc32(upx_byte * in,unsigned relocnum,upx_byte * out,upx_byte * image,int bswap,int * big)975 upx_byte *Packer::optimizeReloc32(upx_byte *in, unsigned relocnum,
976                                   upx_byte *out, upx_byte *image,
977                                   int bswap, int *big)
978 {
979     return optimizeReloc(in, relocnum, out, image, bswap, big, 32);
980 }
981 
optimizeReloc64(upx_byte * in,unsigned relocnum,upx_byte * out,upx_byte * image,int bswap,int * big)982 upx_byte *Packer::optimizeReloc64(upx_byte *in, unsigned relocnum,
983                                   upx_byte *out, upx_byte *image,
984                                   int bswap, int *big)
985 {
986     return optimizeReloc(in, relocnum, out, image, bswap, big, 64);
987 }
988 
989 
unoptimizeReloc(upx_byte ** in,upx_byte * image,MemBuffer * out,int bswap,int bits)990 unsigned Packer::unoptimizeReloc(upx_byte **in, upx_byte *image,
991                                  MemBuffer *out, int bswap, int bits)
992 {
993     upx_byte *p;
994     unsigned relocn = 0;
995     for (p = *in; *p; p++, relocn++)
996         if (*p >= 0xF0)
997         {
998             if (*p == 0xF0 && get_le16(p+1) == 0)
999                 p += 4;
1000             p += 2;
1001         }
1002     //fprintf(stderr,"relocnum=%x\n",relocn);
1003     out->alloc(4*relocn+4); // one extra data
1004     LE32 *outp = (LE32*) (unsigned char *) *out;
1005     LE32 *relocs = outp;
1006     unsigned jc = (unsigned) -4;
1007     for (p = *in; *p; p++)
1008     {
1009         if (*p < 0xF0)
1010             jc += *p;
1011         else
1012         {
1013             unsigned dif = (*p & 0x0F)*0x10000 + get_le16(p+1);
1014             p += 2;
1015             if (dif == 0)
1016             {
1017                 dif = get_le32(p+1);
1018                 p += 4;
1019             }
1020             jc += dif;
1021         }
1022         *relocs++ = jc;
1023         if (bswap && image)
1024         {
1025             if (bits == 32)
1026                 acc_ua_swab32s(image + jc);
1027             else if (bits == 64)
1028                 set_be64(image + jc, get_le64(image + jc));
1029             else
1030                 throwInternalError("unoptimizeReloc problem");
1031         }
1032     }
1033     //fprintf(stderr,"relocnum=%x\n",relocn);
1034     *in = p+1;
1035     return (unsigned) (relocs - outp);
1036 }
1037 
unoptimizeReloc32(upx_byte ** in,upx_byte * image,MemBuffer * out,int bswap)1038 unsigned Packer::unoptimizeReloc32(upx_byte **in, upx_byte *image,
1039                                    MemBuffer *out, int bswap)
1040 {
1041     return unoptimizeReloc(in, image, out, bswap, 32);
1042 }
1043 
unoptimizeReloc64(upx_byte ** in,upx_byte * image,MemBuffer * out,int bswap)1044 unsigned Packer::unoptimizeReloc64(upx_byte **in, upx_byte *image,
1045                                    MemBuffer *out, int bswap)
1046 {
1047     return unoptimizeReloc(in, image, out, bswap, 64);
1048 }
1049 
1050 /*************************************************************************
1051 // loader util (interface to linker)
1052 **************************************************************************/
1053 
getIdentstr(unsigned * size,int small)1054 static const char *getIdentstr(unsigned *size, int small)
1055 {
1056     // IMPORTANT: we do NOT change "http://upx.sf.net"
1057     static char identbig[] =
1058         "\n\0"
1059         "$Info: "
1060         "This file is packed with the UPX executable packer http://upx.sf.net $"
1061         "\n\0"
1062         "$Id: UPX "
1063         UPX_VERSION_STRING4
1064         " Copyright (C) 1996-" UPX_VERSION_YEAR " the UPX Team. All Rights Reserved. $"
1065         "\n";
1066     static char identsmall[] =
1067         "\n"
1068         "$Id: UPX "
1069         "(C) 1996-" UPX_VERSION_YEAR " the UPX Team. All Rights Reserved. http://upx.sf.net $"
1070         "\n";
1071     static char identtiny[] = UPX_VERSION_STRING4;
1072 
1073     static int done;
1074     if (!done && (opt->debug.fake_stub_version[0] || opt->debug.fake_stub_year[0]))
1075     {
1076         struct strinfo_t { char *s; int size; };
1077         static const strinfo_t strlist[] = {
1078             { identbig,   (int)sizeof(identbig) },
1079             { identsmall, (int)sizeof(identsmall) },
1080             { identtiny,  (int)sizeof(identtiny) },
1081         { NULL, 0 } };
1082         const strinfo_t* iter;
1083 
1084         for (iter = strlist; iter->s; ++iter)
1085         {
1086             if (opt->debug.fake_stub_version[0])
1087                 mem_replace(iter->s, iter->size, UPX_VERSION_STRING4, 4, opt->debug.fake_stub_version);
1088             if (opt->debug.fake_stub_year[0])
1089                 mem_replace(iter->s, iter->size, UPX_VERSION_YEAR, 4, opt->debug.fake_stub_year);
1090         }
1091         done = 1;
1092     }
1093 
1094 
1095     if (small < 0)
1096         small = opt->small;
1097     if (small >= 2)
1098     {
1099         *size = sizeof(identtiny);
1100         return identtiny;
1101     }
1102     else if (small >= 1)
1103     {
1104         *size = sizeof(identsmall);
1105         return identsmall;
1106     }
1107     else
1108     {
1109         *size = sizeof(identbig);
1110         return identbig;
1111     }
1112 }
1113 
1114 
initLoader(const void * pdata,int plen,int small)1115 void Packer::initLoader(const void *pdata, int plen, int small)
1116 {
1117     delete linker;
1118     linker = newLinker();
1119     assert(bele == linker->bele);
1120     linker->init(pdata, plen);
1121 
1122     unsigned size;
1123     char const * const ident = getIdentstr(&size, small);
1124     linker->addSection("IDENTSTR", ident, size, 0);
1125 }
1126 
1127 
1128 #define C const char *
1129 #define N ACC_STATIC_CAST(void *, 0)
addLoader(C a)1130 void Packer::addLoader(C a)
1131 { addLoaderVA(a, N); }
addLoader(C a,C b)1132 void Packer::addLoader(C a, C b)
1133 { addLoaderVA(a, b, N); }
addLoader(C a,C b,C c)1134 void Packer::addLoader(C a, C b, C c)
1135 { addLoaderVA(a, b, c, N); }
addLoader(C a,C b,C c,C d)1136 void Packer::addLoader(C a, C b, C c, C d)
1137 { addLoaderVA(a, b, c, d, N); }
addLoader(C a,C b,C c,C d,C e)1138 void Packer::addLoader(C a, C b, C c, C d, C e)
1139 { addLoaderVA(a, b, c, d, e, N); }
addLoader(C a,C b,C c,C d,C e,C f)1140 void Packer::addLoader(C a, C b, C c, C d, C e, C f)
1141 { addLoaderVA(a, b, c, d, e, f, N); }
addLoader(C a,C b,C c,C d,C e,C f,C g)1142 void Packer::addLoader(C a, C b, C c, C d, C e, C f, C g)
1143 { addLoaderVA(a, b, c, d, e, f, g, N); }
addLoader(C a,C b,C c,C d,C e,C f,C g,C h)1144 void Packer::addLoader(C a, C b, C c, C d, C e, C f, C g, C h)
1145 { addLoaderVA(a, b, c, d, e, f, g, h, N); }
addLoader(C a,C b,C c,C d,C e,C f,C g,C h,C i)1146 void Packer::addLoader(C a, C b, C c, C d, C e, C f, C g, C h, C i)
1147 { addLoaderVA(a, b, c, d, e, f, g, h, i, N); }
addLoader(C a,C b,C c,C d,C e,C f,C g,C h,C i,C j)1148 void Packer::addLoader(C a, C b, C c, C d, C e, C f, C g, C h, C i, C j)
1149 { addLoaderVA(a, b, c, d, e, f, g, h, i, j, N); }
1150 #undef C
1151 #undef N
1152 
addLoaderVA(const char * s,...)1153 void __acc_cdecl_va Packer::addLoaderVA(const char *s, ...)
1154 {
1155     va_list ap;
1156     va_start(ap, s);
1157     linker->addLoader(s, ap);
1158     va_end(ap);
1159 }
1160 
getLoader() const1161 upx_byte *Packer::getLoader() const
1162 {
1163     int size = -1;
1164     upx_byte *oloader = linker->getLoader(&size);
1165     if (oloader == NULL || size <= 0)
1166         throwBadLoader();
1167     return oloader;
1168 }
1169 
getLoaderSize() const1170 int Packer::getLoaderSize() const
1171 {
1172     int size = -1;
1173     upx_byte *oloader = linker->getLoader(&size);
1174     if (oloader == NULL || size <= 0)
1175         throwBadLoader();
1176     return size;
1177 }
1178 
hasLoaderSection(const char * name) const1179 bool Packer::hasLoaderSection(const char *name) const
1180 {
1181     void *section = linker->findSection(name, false);
1182     return section != NULL;
1183 }
1184 
getLoaderSection(const char * name,int * slen) const1185 int Packer::getLoaderSection(const char *name, int *slen) const
1186 {
1187     int size = -1;
1188     int ostart = linker->getSection(name, &size);
1189     if (ostart < 0 || size <= 0)
1190         throwBadLoader();
1191     if (slen)
1192         *slen = size;
1193     return ostart;
1194 }
1195 
1196 // same, but the size of the section may be == 0
getLoaderSectionStart(const char * name,int * slen) const1197 int Packer::getLoaderSectionStart(const char *name, int *slen) const
1198 {
1199     int size = -1;
1200     int ostart = linker->getSection(name, &size);
1201     if (ostart < 0 || size < 0)
1202         throwBadLoader();
1203     if (slen)
1204         *slen = size;
1205     return ostart;
1206 }
1207 
1208 
relocateLoader()1209 void Packer::relocateLoader()
1210 {
1211     linker->relocate();
1212 
1213 #if 0
1214     // "relocate" packheader
1215     if (linker->findSection("UPX1HEAD", false))
1216     {
1217         int lsize = -1;
1218         int loff = getLoaderSectionStart("UPX1HEAD", &lsize);
1219         assert(lsize == ph.getPackHeaderSize());
1220         unsigned char *p = getLoader() + loff;
1221         assert(get_le32(p) == UPX_MAGIC_LE32);
1222         //patchPackHeader(p, lsize);
1223         ph.putPackHeader(p);
1224     }
1225 #endif
1226 }
1227 
1228 
1229 /*************************************************************************
1230 // Try compression with several methods and filters, choose the best
1231 /  or first working one. Needs buildLoader().
1232 //
1233 // Required inputs:
1234 //   this->ph
1235 //     ulen
1236 //   parm_ft
1237 //     clevel
1238 //     addvalue
1239 //     buf_len (optional)
1240 //
1241 // - updates this->ph
1242 // - updates *ft
1243 // - i_ptr[] is restored to the original unfiltered version
1244 // - o_ptr[] contains the best compressed version
1245 //
1246 // filter_strategy:
1247 //   n:  try the first N filters, use best one
1248 //  -1:  try all filters, use first working one
1249 //  -2:  try only the opt->filter filter
1250 //  -3:  use no filter at all
1251 //
1252 // This has been prepared for generalization into class Packer so that
1253 // opt->all_methods and/or opt->all_filters are available for all
1254 // executable formats.
1255 //
1256 // It will replace the tryFilters() / compress() call sequence.
1257 //
1258 // 2006-02-15: hdr_buf and hdr_u_len are default empty input "header" array
1259 // to fix a 2-pass problem with Elf headers.  As of today there can be
1260 // only one decompression method per executable output file, and that method
1261 // is the one that gives best compression for .text and loader.  However,
1262 // the Elf headers precede .text in the output file, and are written first.
1263 // "--brute" compression often compressed the Elf headers using nrv2b
1264 // but the .text (and loader) with nrv2e.  This often resulted in SIGSEGV
1265 // during decompression.
1266 // The workaround is for hdr_buf and hdr_u_len to describe the Elf headers
1267 // (typically less than 512 bytes) when .text is passed in, and include
1268 // them in the calculation of shortest output.  Then the result
1269 // this->ph.method  will say which [single] method to use for everything.
1270 // The Elf headers are never filtered.  They are short enough (< 512 bytes)
1271 // that compressing them more than once per method (once here when choosing,
1272 // once again just before writing [because compressWithFilters discards])
1273 // is OK because of the simplicity of not having two output arrays.
1274 **************************************************************************/
1275 
prepareMethods(int * methods,int ph_method,const int * all_methods)1276 static int prepareMethods(int *methods, int ph_method, const int *all_methods)
1277 {
1278     int nmethods = 0;
1279     if (!opt->all_methods || all_methods == NULL)
1280     {
1281         methods[nmethods++] = ph_method;
1282         return nmethods;
1283     }
1284     for (int mm = 0; all_methods[mm] != M_END; ++mm)
1285     {
1286         int method = all_methods[mm];
1287         if (method == M_ULTRA_BRUTE && !opt->ultra_brute)
1288             break;
1289         if (method == M_SKIP || method == M_ULTRA_BRUTE)
1290             continue;
1291         if (opt->all_methods && !opt->all_methods_use_lzma && M_IS_LZMA(method))
1292             continue;
1293         // use this method
1294         assert(Packer::isValidCompressionMethod(method));
1295         methods[nmethods++] = method;
1296     }
1297     return nmethods;
1298 }
1299 
1300 
prepareFilters(int * filters,int & filter_strategy,const int * all_filters)1301 static int prepareFilters(int *filters, int &filter_strategy,
1302                           const int *all_filters)
1303 {
1304     int nfilters = 0;
1305 
1306     // setup filter filter_strategy
1307     if (filter_strategy == 0)
1308     {
1309         if (opt->all_filters)
1310             // choose best from all available filters
1311             filter_strategy = INT_MAX;
1312         else if (opt->filter >= 0 && Filter::isValidFilter(opt->filter, all_filters))
1313             // try opt->filter
1314             filter_strategy = -2;
1315         else
1316             // try the first working filter
1317             filter_strategy = -1;
1318     }
1319     assert(filter_strategy != 0);
1320 
1321     if (filter_strategy == -3)
1322         goto done;
1323     if (filter_strategy == -2)
1324     {
1325         if (opt->filter >= 0 && Filter::isValidFilter(opt->filter, all_filters))
1326         {
1327             filters[nfilters++] = opt->filter;
1328             goto done;
1329         }
1330         filter_strategy = -1;
1331     }
1332     assert(filter_strategy >= -1);
1333 
1334     while (all_filters && *all_filters != FT_END)
1335     {
1336         int filter_id = *all_filters++;
1337         if (filter_id == FT_ULTRA_BRUTE && !opt->ultra_brute)
1338             break;
1339         if (filter_id == FT_SKIP || filter_id == FT_ULTRA_BRUTE)
1340             continue;
1341         if (filter_id == 0)
1342             continue;
1343         // use this filter
1344         assert(Filter::isValidFilter(filter_id));
1345         filters[nfilters++] = filter_id;
1346         if (filter_strategy >= 0 && nfilters >= filter_strategy)
1347             break;
1348     }
1349 
1350 done:
1351     // filter_strategy now only means "stop after first successful filter"
1352     filter_strategy = (filter_strategy < 0) ? -1 : 0;
1353     // make sure that we have a "no filter" fallback
1354     for (int i = 0; i < nfilters; i++)
1355         if (filters[i] == 0)
1356             return nfilters;
1357     filters[nfilters++] = 0;
1358     return nfilters;
1359 }
1360 
1361 
compressWithFilters(upx_bytep i_ptr,unsigned i_len,upx_bytep o_ptr,upx_bytep f_ptr,unsigned f_len,const upx_bytep hdr_ptr,unsigned hdr_len,Filter * parm_ft,const unsigned overlap_range,const upx_compress_config_t * cconf,int filter_strategy,bool inhibit_compression_check)1362 void Packer::compressWithFilters(upx_bytep i_ptr, unsigned i_len,
1363                                  upx_bytep o_ptr,
1364                                  upx_bytep f_ptr, unsigned f_len,
1365                                  const upx_bytep hdr_ptr, unsigned hdr_len,
1366                                  Filter *parm_ft,
1367                                  const unsigned overlap_range,
1368                                  const upx_compress_config_t *cconf,
1369                                  int filter_strategy,
1370                                  bool inhibit_compression_check)
1371 {
1372     parm_ft->buf_len = f_len;
1373     // struct copies
1374     const PackHeader orig_ph = this->ph;
1375           PackHeader best_ph = this->ph;
1376     const Filter orig_ft = *parm_ft;
1377           Filter best_ft = *parm_ft;
1378     //
1379     best_ph.c_len = i_len;
1380     best_ph.overlap_overhead = 0;
1381     unsigned best_ph_lsize = 0;
1382     unsigned best_hdr_c_len = 0;
1383 
1384     // preconditions
1385     assert(orig_ph.filter == 0);
1386     assert(orig_ft.id == 0);
1387 
1388     // prepare methods and filters
1389     int methods[256];
1390     int nmethods = prepareMethods(methods, ph.method, getCompressionMethods(M_ALL, ph.level));
1391     assert(nmethods > 0); assert(nmethods < 256);
1392     int filters[256];
1393     int nfilters = prepareFilters(filters, filter_strategy, getFilters());
1394     assert(nfilters > 0); assert(nfilters < 256);
1395 #if 0
1396     printf("compressWithFilters: m(%d):", nmethods);
1397     for (int i = 0; i < nmethods; i++) printf(" %d", methods[i]);
1398     printf(" f(%d):", nfilters);
1399     for (int i = 0; i < nfilters; i++) printf(" %d", filters[i]);
1400     printf("\n");
1401 #endif
1402 
1403     // update total_passes; previous (ui_total_passes > 0) means incremental
1404     if (uip->ui_total_passes > 0)
1405         uip->ui_total_passes -= 1;
1406     if (filter_strategy < 0)
1407         uip->ui_total_passes += nmethods;
1408     else
1409         uip->ui_total_passes += nfilters * nmethods;
1410 
1411     // Working buffer for compressed data. Don't waste memory and allocate as needed.
1412     upx_bytep o_tmp = o_ptr;
1413     MemBuffer o_tmp_buf;
1414 
1415     // compress using all methods/filters
1416     int nfilters_success_total = 0;
1417     for (int mm = 0; mm < nmethods; mm++) // for all methods
1418     {
1419         assert(isValidCompressionMethod(methods[mm]));
1420         unsigned hdr_c_len = 0;
1421         if (hdr_ptr != NULL && hdr_len)
1422         {
1423             if (nfilters_success_total != 0 && o_tmp == o_ptr)
1424             {
1425                 // do not overwrite o_ptr
1426                 o_tmp_buf.allocForCompression(UPX_MAX(hdr_len, i_len));
1427                 o_tmp = o_tmp_buf;
1428             }
1429             int r = upx_compress(hdr_ptr, hdr_len, o_tmp, &hdr_c_len,
1430                                  NULL, methods[mm], 10, NULL, NULL);
1431             if (r != UPX_E_OK)
1432                 throwInternalError("header compression failed");
1433             if (hdr_c_len >= hdr_len)
1434                 throwInternalError("header compression size increase");
1435         }
1436         int nfilters_success_mm = 0;
1437         for (int ff = 0; ff < nfilters; ff++) // for all filters
1438         {
1439             assert(isValidFilter(filters[ff]));
1440             // get fresh packheader
1441             ph = orig_ph;
1442             ph.method = methods[mm];
1443             ph.filter = filters[ff];
1444             ph.overlap_overhead = 0;
1445             // get fresh filter
1446             Filter ft = orig_ft;
1447             ft.init(ph.filter, orig_ft.addvalue);
1448             // filter
1449             optimizeFilter(&ft, f_ptr, f_len);
1450             bool success = ft.filter(f_ptr, f_len);
1451             if (ft.id != 0 && ft.calls == 0)
1452             {
1453                 // filter did not do anything - no need to call ft.unfilter()
1454                 success = false;
1455             }
1456             if (!success)
1457             {
1458                 // filter failed or was useless
1459                 if (filter_strategy >= 0)
1460                 {
1461                     // adjust ui passes
1462                     if (uip->ui_pass >= 0)
1463                         uip->ui_pass++;
1464                 }
1465                 continue;
1466             }
1467             // filter success
1468 #if 0
1469             printf("filter: id 0x%02x size %6d, calls %5d/%5d/%3d/%5d/%5d, cto 0x%02x\n",
1470                    ft.id, ft.buf_len, ft.calls, ft.noncalls, ft.wrongcalls, ft.firstcall, ft.lastcall, ft.cto);
1471 #endif
1472             if (nfilters_success_total != 0 && o_tmp == o_ptr)
1473             {
1474                 o_tmp_buf.allocForCompression(i_len);
1475                 o_tmp = o_tmp_buf;
1476             }
1477             nfilters_success_total++;
1478             nfilters_success_mm++;
1479             ph.filter_cto = ft.cto;
1480             ph.n_mru = ft.n_mru;
1481             // compress
1482             if (compress(i_ptr, i_len, o_tmp, cconf))
1483             {
1484                 unsigned lsize = 0;
1485                 // findOverlapOperhead() might be slow; omit if already too big.
1486                 if (ph.c_len + lsize + hdr_c_len <= best_ph.c_len + best_ph_lsize + best_hdr_c_len)
1487                 {
1488                     // get results
1489                     ph.overlap_overhead = findOverlapOverhead(o_tmp, i_ptr, overlap_range);
1490                     buildLoader(&ft);
1491                     lsize = getLoaderSize();
1492                     assert(lsize > 0);
1493                 }
1494 #if 0  //{
1495                 printf("\n%2d %02x: %d +%4d +%3d = %d  (best: %d +%4d +%3d = %d)\n", ph.method, ph.filter,
1496                        ph.c_len, lsize, hdr_c_len, ph.c_len + lsize + hdr_c_len,
1497                        best_ph.c_len, best_ph_lsize, best_hdr_c_len, best_ph.c_len + best_ph_lsize + best_hdr_c_len);
1498 #endif  //}
1499                 bool update = false;
1500                 if (ph.c_len + lsize + hdr_c_len < best_ph.c_len + best_ph_lsize + best_hdr_c_len)
1501                     update = true;
1502                 else if (ph.c_len + lsize + hdr_c_len == best_ph.c_len + best_ph_lsize + best_hdr_c_len)
1503                 {
1504                     // prefer smaller loaders
1505                     if (lsize  + hdr_c_len < best_ph_lsize + best_hdr_c_len)
1506                         update = true;
1507                     else if (lsize + hdr_c_len == best_ph_lsize + best_hdr_c_len)
1508                     {
1509                         // prefer less overlap_overhead
1510                         if (ph.overlap_overhead < best_ph.overlap_overhead)
1511                             update = true;
1512                     }
1513                 }
1514                 if (update)
1515                 {
1516                     assert((int)ph.overlap_overhead > 0);
1517                     // update o_ptr[] with best version
1518                     if (o_tmp != o_ptr)
1519                         memcpy(o_ptr, o_tmp, ph.c_len);
1520                     // save compression results
1521                     best_ph = ph;
1522                     best_ph_lsize = lsize;
1523                     best_hdr_c_len = hdr_c_len;
1524                     best_ft = ft;
1525                 }
1526             }
1527             // restore - unfilter with verify
1528             ft.unfilter(f_ptr, f_len, true);
1529             if (filter_strategy < 0)
1530                 break;
1531         }
1532         assert(nfilters_success_mm > 0);
1533     }
1534 
1535     // postconditions 1)
1536     assert(nfilters_success_total > 0);
1537     assert(best_ph.u_len == orig_ph.u_len);
1538     assert(best_ph.filter == best_ft.id);
1539     assert(best_ph.filter_cto == best_ft.cto);
1540     // FIXME  assert(best_ph.n_mru == best_ft.n_mru);
1541 
1542     // copy back results
1543     this->ph = best_ph;
1544     *parm_ft = best_ft;
1545 
1546     // Finally, check compression ratio.
1547     // Might be inhibited when blocksize < file_size, for instance.
1548     if (!inhibit_compression_check) {
1549         if (best_ph.c_len + best_ph_lsize >= best_ph.u_len)
1550             throwNotCompressible();
1551         if (!checkCompressionRatio(best_ph.u_len, best_ph.c_len))
1552             throwNotCompressible();
1553 
1554         // postconditions 2)
1555         assert(best_ph.overlap_overhead > 0);
1556     }
1557 
1558     // convenience
1559     buildLoader(&best_ft);
1560 }
1561 
1562 
1563 /*************************************************************************
1564 //
1565 **************************************************************************/
1566 
compressWithFilters(Filter * ft,const unsigned overlap_range,const upx_compress_config_t * cconf,int filter_strategy,bool inhibit_compression_check)1567 void Packer::compressWithFilters(Filter *ft,
1568                                  const unsigned overlap_range,
1569                                  const upx_compress_config_t *cconf,
1570                                  int filter_strategy,
1571                                  bool inhibit_compression_check)
1572 {
1573     compressWithFilters(ft, overlap_range, cconf, filter_strategy,
1574                         0, 0, 0, NULL, 0, inhibit_compression_check);
1575 }
1576 
1577 
compressWithFilters(Filter * ft,const unsigned overlap_range,const upx_compress_config_t * cconf,int filter_strategy,unsigned filter_off,unsigned ibuf_off,unsigned obuf_off,const upx_bytep hdr_ptr,unsigned hdr_len,bool inhibit_compression_check)1578 void Packer::compressWithFilters(Filter *ft,
1579                                  const unsigned overlap_range,
1580                                  const upx_compress_config_t *cconf,
1581                                  int filter_strategy,
1582                                  unsigned filter_off,
1583                                  unsigned ibuf_off,
1584                                  unsigned obuf_off,
1585                                  const upx_bytep hdr_ptr, unsigned hdr_len,
1586                                  bool inhibit_compression_check)
1587 {
1588     ibuf.checkState(); obuf.checkState();
1589 
1590     upx_bytep i_ptr = ibuf + ibuf_off;
1591     unsigned  i_len = ph.u_len;
1592     upx_bytep o_ptr = obuf + obuf_off;
1593     upx_bytep f_ptr = ibuf + filter_off;
1594     unsigned  f_len = ft->buf_len ? ft->buf_len : i_len;
1595 
1596     assert(f_ptr + f_len <= i_ptr + i_len);
1597 
1598     compressWithFilters(i_ptr, i_len,
1599                         o_ptr,
1600                         f_ptr, f_len,
1601                         hdr_ptr, hdr_len,
1602                         ft, overlap_range, cconf, filter_strategy,
1603                         inhibit_compression_check);
1604 
1605     ibuf.checkState(); obuf.checkState();
1606 }
1607 
1608 /* vim:set ts=4 sw=4 et: */
1609