1 /* util.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 #include "conf.h"
29 #include "util.h"
30 
31 #if (ACC_CC_MSC && (_MSC_VER >= 1000 && _MSC_VER < 1200))
32 /* avoid -W4 warnings in <conio.h> */
33 #pragma warning(disable : 4032)
34 /* avoid -W4 warnings in <windows.h> */
35 #pragma warning(disable : 4201 4214 4514)
36 #endif
37 #define ACC_WANT_ACC_INCI_H 1
38 #include "miniacc.h"
39 #define ACC_WANT_ACCLIB_GETOPT 1
40 #define ACC_WANT_ACCLIB_HSREAD 1
41 #define ACC_WANT_ACCLIB_MISC 1
42 #define ACC_WANT_ACCLIB_UA 1
43 #define ACC_WANT_ACCLIB_WILDARGV 1
44 #undef HAVE_MKDIR
45 #include "miniacc.h"
46 
47 /*************************************************************************
48 // assert sane memory buffer sizes to protect against integer overflows
49 // and malicious header fields
50 **************************************************************************/
51 
52 ACC_COMPILE_TIME_ASSERT_HEADER(UPX_RSIZE_MAX_MEM == UPX_RSIZE_MAX)
53 ACC_COMPILE_TIME_ASSERT_HEADER(UPX_RSIZE_MAX_STR <= UPX_RSIZE_MAX / 256)
54 ACC_COMPILE_TIME_ASSERT_HEADER(2ull * UPX_RSIZE_MAX * 9 / 8 + 16 * 1024 * 1024 < INT_MAX)
55 
mem_size(upx_uint64_t element_size,upx_uint64_t n,upx_uint64_t extra1,upx_uint64_t extra2)56 upx_rsize_t mem_size(upx_uint64_t element_size, upx_uint64_t n, upx_uint64_t extra1,
57                      upx_uint64_t extra2) {
58     assert(element_size > 0);
59     if (element_size > UPX_RSIZE_MAX)
60         throwCantPack("mem_size 1; take care");
61     if (n > UPX_RSIZE_MAX)
62         throwCantPack("mem_size 2; take care");
63     if (extra1 > UPX_RSIZE_MAX)
64         throwCantPack("mem_size 3; take care");
65     if (extra2 > UPX_RSIZE_MAX)
66         throwCantPack("mem_size 4; take care");
67     upx_uint64_t bytes = element_size * n + extra1 + extra2; // cannot overflow
68     if (bytes > UPX_RSIZE_MAX)
69         throwCantPack("mem_size 5; take care");
70     return ACC_ICONV(upx_rsize_t, bytes);
71 }
72 
mem_size_get_n(upx_uint64_t element_size,upx_uint64_t n)73 upx_rsize_t mem_size_get_n(upx_uint64_t element_size, upx_uint64_t n) {
74     mem_size_assert(element_size, n);
75     return ACC_ICONV(upx_rsize_t, n); // return n
76 }
77 
mem_size_valid(upx_uint64_t element_size,upx_uint64_t n,upx_uint64_t extra1,upx_uint64_t extra2)78 bool mem_size_valid(upx_uint64_t element_size, upx_uint64_t n, upx_uint64_t extra1,
79                     upx_uint64_t extra2) {
80     assert(element_size > 0);
81     if (element_size > UPX_RSIZE_MAX)
82         return false;
83     if (n > UPX_RSIZE_MAX)
84         return false;
85     if (extra1 > UPX_RSIZE_MAX)
86         return false;
87     if (extra2 > UPX_RSIZE_MAX)
88         return false;
89     upx_uint64_t bytes = element_size * n + extra1 + extra2; // cannot overflow
90     if (bytes > UPX_RSIZE_MAX)
91         return false;
92     return true;
93 }
94 
mem_size_valid_bytes(upx_uint64_t bytes)95 bool mem_size_valid_bytes(upx_uint64_t bytes) {
96     if (bytes > UPX_RSIZE_MAX)
97         return false;
98     return true;
99 }
100 
ptr_diff(const void * p1,const void * p2)101 int ptr_diff(const void *p1, const void *p2) {
102     assert(p1 != NULL);
103     assert(p2 != NULL);
104     ptrdiff_t d = (const char *) p1 - (const char *) p2;
105     if (p1 >= p2)
106         assert(mem_size_valid_bytes(d));
107     else
108         assert(mem_size_valid_bytes(-d));
109     return ACC_ICONV(int, d);
110 }
111 
ptr_udiff(const void * p1,const void * p2)112 unsigned ptr_udiff(const void *p1, const void *p2) {
113     int d = ptr_diff(p1, p2);
114     assert(d >= 0);
115     return ACC_ICONV(unsigned, d);
116 }
117 
mem_clear(void * p,size_t n)118 void mem_clear(void *p, size_t n) {
119     mem_size_assert(1, n);
120     memset(p, 0, n);
121 }
122 
123 /*************************************************************************
124 // bele.h
125 **************************************************************************/
126 
127 namespace N_BELE_CTP {
128 const BEPolicy be_policy;
129 const LEPolicy le_policy;
130 } // namespace N_BELE_CTP
131 
132 namespace N_BELE_RTP {
133 const BEPolicy be_policy;
134 const LEPolicy le_policy;
135 } // namespace N_BELE_RTP
136 
137 /*************************************************************************
138 // qsort() util
139 **************************************************************************/
140 
be16_compare(const void * e1,const void * e2)141 int __acc_cdecl_qsort be16_compare(const void *e1, const void *e2) {
142     const unsigned d1 = get_be16(e1);
143     const unsigned d2 = get_be16(e2);
144     return (d1 < d2) ? -1 : ((d1 > d2) ? 1 : 0);
145 }
146 
be24_compare(const void * e1,const void * e2)147 int __acc_cdecl_qsort be24_compare(const void *e1, const void *e2) {
148     const unsigned d1 = get_be24(e1);
149     const unsigned d2 = get_be24(e2);
150     return (d1 < d2) ? -1 : ((d1 > d2) ? 1 : 0);
151 }
152 
be32_compare(const void * e1,const void * e2)153 int __acc_cdecl_qsort be32_compare(const void *e1, const void *e2) {
154     const unsigned d1 = get_be32(e1);
155     const unsigned d2 = get_be32(e2);
156     return (d1 < d2) ? -1 : ((d1 > d2) ? 1 : 0);
157 }
158 
be64_compare(const void * e1,const void * e2)159 int __acc_cdecl_qsort be64_compare(const void *e1, const void *e2) {
160     const upx_uint64_t d1 = get_be64(e1);
161     const upx_uint64_t d2 = get_be64(e2);
162     return (d1 < d2) ? -1 : ((d1 > d2) ? 1 : 0);
163 }
164 
le16_compare(const void * e1,const void * e2)165 int __acc_cdecl_qsort le16_compare(const void *e1, const void *e2) {
166     const unsigned d1 = get_le16(e1);
167     const unsigned d2 = get_le16(e2);
168     return (d1 < d2) ? -1 : ((d1 > d2) ? 1 : 0);
169 }
170 
le24_compare(const void * e1,const void * e2)171 int __acc_cdecl_qsort le24_compare(const void *e1, const void *e2) {
172     const unsigned d1 = get_le24(e1);
173     const unsigned d2 = get_le24(e2);
174     return (d1 < d2) ? -1 : ((d1 > d2) ? 1 : 0);
175 }
176 
le32_compare(const void * e1,const void * e2)177 int __acc_cdecl_qsort le32_compare(const void *e1, const void *e2) {
178     const unsigned d1 = get_le32(e1);
179     const unsigned d2 = get_le32(e2);
180     return (d1 < d2) ? -1 : ((d1 > d2) ? 1 : 0);
181 }
182 
le64_compare(const void * e1,const void * e2)183 int __acc_cdecl_qsort le64_compare(const void *e1, const void *e2) {
184     const upx_uint64_t d1 = get_le64(e1);
185     const upx_uint64_t d2 = get_le64(e2);
186     return (d1 < d2) ? -1 : ((d1 > d2) ? 1 : 0);
187 }
188 
be16_compare_signed(const void * e1,const void * e2)189 int __acc_cdecl_qsort be16_compare_signed(const void *e1, const void *e2) {
190     const int d1 = get_be16_signed(e1);
191     const int d2 = get_be16_signed(e2);
192     return (d1 < d2) ? -1 : ((d1 > d2) ? 1 : 0);
193 }
194 
be24_compare_signed(const void * e1,const void * e2)195 int __acc_cdecl_qsort be24_compare_signed(const void *e1, const void *e2) {
196     const int d1 = get_be24_signed(e1);
197     const int d2 = get_be24_signed(e2);
198     return (d1 < d2) ? -1 : ((d1 > d2) ? 1 : 0);
199 }
200 
be32_compare_signed(const void * e1,const void * e2)201 int __acc_cdecl_qsort be32_compare_signed(const void *e1, const void *e2) {
202     const int d1 = get_be32_signed(e1);
203     const int d2 = get_be32_signed(e2);
204     return (d1 < d2) ? -1 : ((d1 > d2) ? 1 : 0);
205 }
206 
be64_compare_signed(const void * e1,const void * e2)207 int __acc_cdecl_qsort be64_compare_signed(const void *e1, const void *e2) {
208     const upx_int64_t d1 = get_be64_signed(e1);
209     const upx_int64_t d2 = get_be64_signed(e2);
210     return (d1 < d2) ? -1 : ((d1 > d2) ? 1 : 0);
211 }
212 
le16_compare_signed(const void * e1,const void * e2)213 int __acc_cdecl_qsort le16_compare_signed(const void *e1, const void *e2) {
214     const int d1 = get_le16_signed(e1);
215     const int d2 = get_le16_signed(e2);
216     return (d1 < d2) ? -1 : ((d1 > d2) ? 1 : 0);
217 }
218 
le24_compare_signed(const void * e1,const void * e2)219 int __acc_cdecl_qsort le24_compare_signed(const void *e1, const void *e2) {
220     const int d1 = get_le24_signed(e1);
221     const int d2 = get_le24_signed(e2);
222     return (d1 < d2) ? -1 : ((d1 > d2) ? 1 : 0);
223 }
224 
le32_compare_signed(const void * e1,const void * e2)225 int __acc_cdecl_qsort le32_compare_signed(const void *e1, const void *e2) {
226     const int d1 = get_le32_signed(e1);
227     const int d2 = get_le32_signed(e2);
228     return (d1 < d2) ? -1 : ((d1 > d2) ? 1 : 0);
229 }
230 
le64_compare_signed(const void * e1,const void * e2)231 int __acc_cdecl_qsort le64_compare_signed(const void *e1, const void *e2) {
232     const upx_int64_t d1 = get_le64_signed(e1);
233     const upx_int64_t d2 = get_le64_signed(e2);
234     return (d1 < d2) ? -1 : ((d1 > d2) ? 1 : 0);
235 }
236 
237 /*************************************************************************
238 // find util
239 **************************************************************************/
240 
find(const void * b,int blen,const void * what,int wlen)241 int find(const void *b, int blen, const void *what, int wlen) {
242     if (b == NULL || blen <= 0 || what == NULL || wlen <= 0)
243         return -1;
244 
245     int i;
246     const unsigned char *base = (const unsigned char *) b;
247     unsigned char firstc = *(const unsigned char *) what;
248 
249     blen -= wlen;
250     for (i = 0; i <= blen; i++, base++)
251         if (*base == firstc && memcmp(base, what, wlen) == 0)
252             return i;
253 
254     return -1;
255 }
256 
find_be16(const void * b,int blen,unsigned what)257 int find_be16(const void *b, int blen, unsigned what) {
258     unsigned char w[2];
259     set_be16(w, what);
260     return find(b, blen, w, 2);
261 }
262 
find_be32(const void * b,int blen,unsigned what)263 int find_be32(const void *b, int blen, unsigned what) {
264     unsigned char w[4];
265     set_be32(w, what);
266     return find(b, blen, w, 4);
267 }
268 
find_be64(const void * b,int blen,upx_uint64_t what)269 int find_be64(const void *b, int blen, upx_uint64_t what) {
270     unsigned char w[8];
271     set_be64(w, what);
272     return find(b, blen, w, 8);
273 }
274 
find_le16(const void * b,int blen,unsigned what)275 int find_le16(const void *b, int blen, unsigned what) {
276     unsigned char w[2];
277     set_le16(w, what);
278     return find(b, blen, w, 2);
279 }
280 
find_le32(const void * b,int blen,unsigned what)281 int find_le32(const void *b, int blen, unsigned what) {
282     unsigned char w[4];
283     set_le32(w, what);
284     return find(b, blen, w, 4);
285 }
286 
find_le64(const void * b,int blen,upx_uint64_t what)287 int find_le64(const void *b, int blen, upx_uint64_t what) {
288     unsigned char w[8];
289     set_le64(w, what);
290     return find(b, blen, w, 8);
291 }
292 
mem_replace(void * bb,int blen,const void * what,int wlen,const void * r)293 int mem_replace(void *bb, int blen, const void *what, int wlen, const void *r) {
294     unsigned char *b = (unsigned char *) bb;
295     int boff = 0;
296     int n = 0;
297 
298     while (blen - boff >= wlen) {
299         int off = find(b + boff, blen - boff, what, wlen);
300         if (off < 0)
301             break;
302         boff += off;
303         memcpy(b + boff, r, wlen);
304         boff += wlen;
305         n++;
306     }
307     return n;
308 }
309 
310 /*************************************************************************
311 // fn - FileName util
312 **************************************************************************/
313 
314 #if (ACC_OS_CYGWIN || ACC_OS_DOS16 || ACC_OS_DOS32 || ACC_OS_EMX || ACC_OS_OS2 || ACC_OS_OS16 ||   \
315      ACC_OS_TOS || ACC_OS_WIN16 || ACC_OS_WIN32 || ACC_OS_WIN64)
316 
317 static const char dir_sep[] = "/\\";
318 #define fn_is_drive(s) (s[0] && s[1] == ':')
319 #define fn_is_sep(c) (strchr(dir_sep, c) != NULL)
320 #define fn_skip_drive(s) (fn_is_drive(s) ? (s) + 2 : (s))
321 #define fn_tolower(c) (tolower(((unsigned char) (c))))
322 
323 #else
324 
325 // static const char dir_sep[] = "/";
326 #define fn_is_drive(s) (0)
327 #define fn_is_sep(c) ((c) == '/')
328 #define fn_skip_drive(s) (s)
329 #define fn_tolower(c) (c)
330 
331 #endif
332 
fn_basename(const char * name)333 char *fn_basename(const char *name) {
334     const char *n, *nn;
335 
336     name = fn_skip_drive(name);
337     for (nn = n = name; *nn; nn++)
338         if (fn_is_sep(*nn))
339             n = nn + 1;
340     return ACC_UNCONST_CAST(char *, n);
341 }
342 
fn_has_ext(const char * name,const char * ext,bool ignore_case)343 bool fn_has_ext(const char *name, const char *ext, bool ignore_case) {
344     const char *n, *e;
345 
346     name = fn_basename(name);
347     for (n = e = name; *n; n++)
348         if (*n == '.')
349             e = n;
350     if (ignore_case)
351         return (strcasecmp(ext, e + 1) == 0);
352     else
353         return (fn_strcmp(ext, e + 1) == 0);
354 }
355 
fn_strlwr(char * n)356 char *fn_strlwr(char *n) {
357     char *p;
358     for (p = n; *p; p++)
359         *p = (char) fn_tolower(*p);
360     return n;
361 }
362 
fn_strcmp(const char * n1,const char * n2)363 int fn_strcmp(const char *n1, const char *n2) {
364     for (;;) {
365         if (*n1 != *n2) {
366             int c = fn_tolower(*n1) - fn_tolower(*n2);
367             if (c)
368                 return c;
369         }
370         if (*n1 == 0)
371             return 0;
372         n1++;
373         n2++;
374     }
375 }
376 
377 /*************************************************************************
378 // misc.
379 **************************************************************************/
380 
set_method_name(char * buf,size_t size,int method,int level)381 bool set_method_name(char *buf, size_t size, int method, int level) {
382     bool r = true;
383     const char *alg;
384     if (M_IS_NRV2B(method))
385         alg = "NRV2B";
386     else if (M_IS_NRV2D(method))
387         alg = "NRV2D";
388     else if (M_IS_NRV2E(method))
389         alg = "NRV2E";
390     else if (M_IS_LZMA(method))
391         alg = "LZMA";
392     else {
393         alg = "???";
394         r = false;
395     }
396     if (level > 0)
397         upx_snprintf(buf, size, "%s/%d", alg, level);
398     else
399         upx_snprintf(buf, size, "%s", alg);
400     return r;
401 }
402 
center_string(char * buf,size_t size,const char * s)403 void center_string(char *buf, size_t size, const char *s) {
404     size_t l1 = size - 1;
405     size_t l2 = strlen(s);
406     assert(size > 0);
407     assert(l2 < size);
408     memset(buf, ' ', l1);
409     memcpy(buf + (l1 - l2) / 2, s, l2);
410     buf[l1] = 0;
411 }
412 
file_exists(const char * name)413 bool file_exists(const char *name) {
414     int fd, r;
415     struct stat st;
416 
417     /* return true if we can open it */
418     fd = open(name, O_RDONLY | O_BINARY, 0);
419     if (fd >= 0) {
420         (void) close(fd);
421         return true;
422     }
423 
424     /* return true if we can stat it */
425     // memset(&st, 0, sizeof(st));
426     r = stat(name, &st);
427     if (r != -1)
428         return true;
429 
430 /* return true if we can lstat it */
431 #if (HAVE_LSTAT)
432     // memset(&st, 0, sizeof(st));
433     r = lstat(name, &st);
434     if (r != -1)
435         return true;
436 #endif
437 
438     return false;
439 }
440 
maketempname(char * ofilename,size_t size,const char * ifilename,const char * ext,bool force)441 bool maketempname(char *ofilename, size_t size, const char *ifilename, const char *ext,
442                   bool force) {
443     char *ofext = NULL, *ofname;
444     int ofile;
445 
446     if (size <= 0)
447         return false;
448 
449     strcpy(ofilename, ifilename);
450     for (ofname = fn_basename(ofilename); *ofname; ofname++) {
451         if (*ofname == '.')
452             ofext = ofname;
453     }
454     if (ofext == NULL)
455         ofext = ofilename + strlen(ofilename);
456     strcpy(ofext, ext);
457 
458     for (ofile = 0; ofile < 1000; ofile++) {
459         assert(strlen(ofilename) < size);
460         if (!file_exists(ofilename))
461             return true;
462         if (!force)
463             break;
464         upx_snprintf(ofext, 5, ".%03d", ofile);
465     }
466 
467     ofilename[0] = 0;
468     return false;
469 }
470 
makebakname(char * ofilename,size_t size,const char * ifilename,bool force)471 bool makebakname(char *ofilename, size_t size, const char *ifilename, bool force) {
472     char *ofext = NULL, *ofname;
473     int ofile;
474 
475     if (size <= 0)
476         return false;
477 
478     strcpy(ofilename, ifilename);
479     for (ofname = fn_basename(ofilename); *ofname; ofname++) {
480         if (*ofname == '.')
481             ofext = ofname;
482     }
483     if (ofext == NULL) {
484         ofext = ofilename + strlen(ofilename);
485         strcpy(ofext, ".~");
486     } else if (strlen(ofext) < 1 + 3)
487         strcat(ofilename, "~");
488     else
489         ofext[strlen(ofext) - 1] = '~';
490 
491     for (ofile = 0; ofile < 1000; ofile++) {
492         assert(strlen(ofilename) < size);
493         if (!file_exists(ofilename))
494             return true;
495         if (!force)
496             break;
497         upx_snprintf(ofext, 5, ".%03d", ofile);
498     }
499 
500     ofilename[0] = 0;
501     return false;
502 }
503 
504 /*************************************************************************
505 // return compression ratio, where 100% == 1000*1000 == 1e6
506 **************************************************************************/
507 
get_ratio(upx_uint64_t u_len,upx_uint64_t c_len)508 unsigned get_ratio(upx_uint64_t u_len, upx_uint64_t c_len) {
509     const unsigned n = 1000 * 1000;
510     if (u_len == 0)
511         return c_len == 0 ? 0 : n;
512     upx_uint64_t x = c_len * n;
513     assert(x / n == c_len);
514     x /= u_len;
515     x += 50;         // rounding
516     if (x >= 10 * n) // >= "1000%"
517         x = 10 * n - 1;
518     return ACC_ICONV(unsigned, x);
519 }
520 
521 /*************************************************************************
522 // Don't link these functions from libc ==> save xxx bytes
523 **************************************************************************/
524 
525 extern "C" {
526 
527 // FIXME - quick hack for arm-wince-gcc-3.4 (Debian pocketpc-*.deb packages)
528 #if 1 && (ACC_ARCH_ARM) && defined(__pe__) && !defined(__CEGCC__) && !defined(_WIN32)
dup(int fd)529 int dup(int fd) {
530     UNUSED(fd);
531     return -1;
532 }
533 #endif
534 
535 #if (ACC_OS_DOS32) && defined(__DJGPP__)
536 // int _is_executable(const char *, int, const char *) { return 0; }
537 
538 // FIXME: something wants to link in ctime.o
539 // time_t mktime(struct tm *) { return 0; }
540 
541 // time_t time(time_t *t) { if (t) *t = 0; return 0; }
542 #endif
543 
544 } // extern "C"
545 
546 /* vim:set ts=4 sw=4 et: */
547