mirror of
https://github.com/upx/upx
synced 2025-09-28 19:06:07 +08:00
Some refactoring. NFC.
This commit is contained in:
parent
fab0c3b09d
commit
b0207ce524
|
@ -631,7 +631,7 @@ struct upx_compress_result_t
|
||||||
// globals
|
// globals
|
||||||
**************************************************************************/
|
**************************************************************************/
|
||||||
|
|
||||||
#include "snprintf.h"
|
#include "snprintf.h" // must get included first!
|
||||||
#include "stdcxx.h"
|
#include "stdcxx.h"
|
||||||
#include "options.h"
|
#include "options.h"
|
||||||
#include "except.h"
|
#include "except.h"
|
||||||
|
|
59
src/mem.cpp
59
src/mem.cpp
|
@ -30,65 +30,6 @@
|
||||||
#include "mem.h"
|
#include "mem.h"
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
// assert sane memory buffer sizes to protect against integer overflows
|
|
||||||
// and malicious header fields
|
|
||||||
**************************************************************************/
|
|
||||||
|
|
||||||
ACC_COMPILE_TIME_ASSERT_HEADER(UPX_RSIZE_MAX_MEM == UPX_RSIZE_MAX)
|
|
||||||
ACC_COMPILE_TIME_ASSERT_HEADER(UPX_RSIZE_MAX_STR <= UPX_RSIZE_MAX / 256)
|
|
||||||
ACC_COMPILE_TIME_ASSERT_HEADER(2ull * UPX_RSIZE_MAX * 9 / 8 + 16*1024*1024 < INT_MAX)
|
|
||||||
|
|
||||||
upx_rsize_t mem_size(upx_uint64_t element_size, upx_uint64_t n, upx_uint64_t extra1, upx_uint64_t extra2)
|
|
||||||
{
|
|
||||||
assert(element_size > 0);
|
|
||||||
if (element_size > UPX_RSIZE_MAX) throwCantPack("mem_size 1; take care");
|
|
||||||
if (n > UPX_RSIZE_MAX) throwCantPack("mem_size 2; take care");
|
|
||||||
if (extra1 > UPX_RSIZE_MAX) throwCantPack("mem_size 3; take care");
|
|
||||||
if (extra2 > UPX_RSIZE_MAX) throwCantPack("mem_size 4; take care");
|
|
||||||
upx_uint64_t bytes = element_size * n + extra1 + extra2; // cannot overflow
|
|
||||||
if (bytes > UPX_RSIZE_MAX) throwCantPack("mem_size 5; take care");
|
|
||||||
return ACC_ICONV(upx_rsize_t, bytes);
|
|
||||||
}
|
|
||||||
|
|
||||||
upx_rsize_t mem_size_get_n(upx_uint64_t element_size, upx_uint64_t n)
|
|
||||||
{
|
|
||||||
mem_size_assert(element_size, n);
|
|
||||||
return ACC_ICONV(upx_rsize_t, n); // return n
|
|
||||||
}
|
|
||||||
|
|
||||||
bool mem_size_valid(upx_uint64_t element_size, upx_uint64_t n, upx_uint64_t extra1, upx_uint64_t extra2)
|
|
||||||
{
|
|
||||||
assert(element_size > 0);
|
|
||||||
if (element_size > UPX_RSIZE_MAX) return false;
|
|
||||||
if (n > UPX_RSIZE_MAX) return false;
|
|
||||||
if (extra1 > UPX_RSIZE_MAX) return false;
|
|
||||||
if (extra2 > UPX_RSIZE_MAX) return false;
|
|
||||||
upx_uint64_t bytes = element_size * n + extra1 + extra2; // cannot overflow
|
|
||||||
if (bytes > UPX_RSIZE_MAX) return false;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool mem_size_valid_bytes(upx_uint64_t bytes)
|
|
||||||
{
|
|
||||||
if (bytes > UPX_RSIZE_MAX) return false;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int ptr_diff(const void *p1, const void *p2)
|
|
||||||
{
|
|
||||||
assert(p1 != NULL);
|
|
||||||
assert(p2 != NULL);
|
|
||||||
ptrdiff_t d = (const char *)p1 - (const char *)p2;
|
|
||||||
if (p1 >= p2)
|
|
||||||
assert(mem_size_valid_bytes(d));
|
|
||||||
else
|
|
||||||
assert(mem_size_valid_bytes(-d));
|
|
||||||
return ACC_ICONV(int, d);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
/*************************************************************************
|
||||||
// bool use_simple_mcheck()
|
// bool use_simple_mcheck()
|
||||||
**************************************************************************/
|
**************************************************************************/
|
||||||
|
|
|
@ -614,7 +614,7 @@ class PeFile::ImportLinker : public ElfLinkerAMD64
|
||||||
unsigned len = 1 + 2 * strlen(dll) + 1 + 2 * strlen(proc) + 1 + 1;
|
unsigned len = 1 + 2 * strlen(dll) + 1 + 2 * strlen(proc) + 1 + 1;
|
||||||
tstr dlln(name_for_dll(dll, first_char));
|
tstr dlln(name_for_dll(dll, first_char));
|
||||||
char *procn = New(char, len);
|
char *procn = New(char, len);
|
||||||
upx_snprintf(procn, len - 1, "%s%c", (const char*) dlln, separator);
|
upx_snprintf(procn, len, "%s%c", (const char*) dlln, separator);
|
||||||
encode_name(proc, procn + strlen(procn));
|
encode_name(proc, procn + strlen(procn));
|
||||||
return procn;
|
return procn;
|
||||||
}
|
}
|
||||||
|
|
|
@ -745,35 +745,35 @@ static size_t dopr(char *buffer, size_t maxsize, const char *format, va_list arg
|
||||||
**************************************************************************/
|
**************************************************************************/
|
||||||
|
|
||||||
// UPX version with assertions
|
// UPX version with assertions
|
||||||
int upx_vsnprintf(char *str, size_t count, const char *format, va_list ap) {
|
int upx_vsnprintf(char *str, upx_rsize_t max_size, const char *format, va_list ap) {
|
||||||
size_t size;
|
size_t size;
|
||||||
|
|
||||||
// preconditions
|
// preconditions
|
||||||
assert(count <= UPX_RSIZE_MAX_STR);
|
assert(max_size <= UPX_RSIZE_MAX_STR);
|
||||||
if (str != NULL)
|
if (str != NULL)
|
||||||
assert(count > 0);
|
assert(max_size > 0);
|
||||||
else
|
else
|
||||||
assert(count == 0);
|
assert(max_size == 0);
|
||||||
|
|
||||||
size = dopr(str, count, format, ap);
|
size = dopr(str, max_size, format, ap);
|
||||||
|
|
||||||
// postconditions
|
// postconditions
|
||||||
assert(size > 0);
|
assert(size > 0);
|
||||||
assert(size <= UPX_RSIZE_MAX_STR);
|
assert(size <= UPX_RSIZE_MAX_STR);
|
||||||
if (str != NULL) {
|
if (str != NULL) {
|
||||||
assert(size <= count);
|
assert(size <= max_size);
|
||||||
assert(str[size - 1] == '\0');
|
assert(str[size - 1] == '\0');
|
||||||
}
|
}
|
||||||
|
|
||||||
return ACC_ICONV(int, size - 1); // snprintf() returns length, not size
|
return ACC_ICONV(int, size - 1); // snprintf() returns length, not size
|
||||||
}
|
}
|
||||||
|
|
||||||
int __acc_cdecl_va upx_snprintf(char *str, size_t count, const char *format, ...) {
|
int __acc_cdecl_va upx_snprintf(char *str, upx_rsize_t max_size, const char *format, ...) {
|
||||||
va_list ap;
|
va_list ap;
|
||||||
int len;
|
int len;
|
||||||
|
|
||||||
va_start(ap, format);
|
va_start(ap, format);
|
||||||
len = upx_vsnprintf(str, count, format, ap);
|
len = upx_vsnprintf(str, max_size, format, ap);
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,31 +28,50 @@
|
||||||
#ifndef __UPX_SNPRINTF_H
|
#ifndef __UPX_SNPRINTF_H
|
||||||
#define __UPX_SNPRINTF_H 1
|
#define __UPX_SNPRINTF_H 1
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*************************************************************************
|
/*************************************************************************
|
||||||
//
|
//
|
||||||
**************************************************************************/
|
**************************************************************************/
|
||||||
|
|
||||||
int upx_vsnprintf(char *str, size_t count, const char *format, va_list ap);
|
#ifdef __cplusplus
|
||||||
int __acc_cdecl_va upx_snprintf (char *str, size_t count, const char *format, ...);
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// info: snprintf() returns length and NOT size, but max_size is indeed size (incl NUL)
|
||||||
|
int upx_vsnprintf(char *str, upx_rsize_t max_size, const char *format, va_list ap);
|
||||||
|
int __acc_cdecl_va upx_snprintf (char *str, upx_rsize_t max_size, const char *format, ...);
|
||||||
int upx_vasprintf(char **ptr, const char *format, va_list ap);
|
int upx_vasprintf(char **ptr, const char *format, va_list ap);
|
||||||
int __acc_cdecl_va upx_asprintf (char **ptr, const char *format, ...);
|
int __acc_cdecl_va upx_asprintf (char **ptr, const char *format, ...);
|
||||||
|
|
||||||
#undef sprintf
|
|
||||||
#define sprintf error_sprintf_is_dangerous_use_snprintf
|
|
||||||
|
|
||||||
upx_rsize_t upx_strlen(const char *);
|
upx_rsize_t upx_strlen(const char *);
|
||||||
|
|
||||||
#undef strlen
|
|
||||||
#define strlen upx_strlen
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// globally redirect some functions
|
||||||
|
#undef sprintf
|
||||||
|
#define sprintf error_sprintf_is_dangerous_use_snprintf
|
||||||
|
#undef strlen
|
||||||
|
#define strlen upx_strlen
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
// some unsigned char string support functions
|
||||||
|
**************************************************************************/
|
||||||
|
|
||||||
|
inline unsigned char *strcpy(unsigned char *s1, const unsigned char *s2) {
|
||||||
|
return (unsigned char *) strcpy((char *) s1, (const char *) s2);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline int strcmp(const unsigned char *s1, const unsigned char *s2) {
|
||||||
|
return strcmp((const char *) s1, (const char *) s2);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline int strcasecmp(const unsigned char *s1, const unsigned char *s2) {
|
||||||
|
return strcasecmp((const char *) s1, (const char *) s2);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline size_t strlen(const unsigned char *s) { return strlen((const char *) s); }
|
||||||
|
|
||||||
#endif /* already included */
|
#endif /* already included */
|
||||||
|
|
||||||
/* vim:set ts=4 sw=4 et: */
|
/* vim:set ts=4 sw=4 et: */
|
||||||
|
|
66
src/util.cpp
66
src/util.cpp
|
@ -46,6 +46,72 @@
|
||||||
#include "miniacc.h"
|
#include "miniacc.h"
|
||||||
|
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
// assert sane memory buffer sizes to protect against integer overflows
|
||||||
|
// and malicious header fields
|
||||||
|
**************************************************************************/
|
||||||
|
|
||||||
|
ACC_COMPILE_TIME_ASSERT_HEADER(UPX_RSIZE_MAX_MEM == UPX_RSIZE_MAX)
|
||||||
|
ACC_COMPILE_TIME_ASSERT_HEADER(UPX_RSIZE_MAX_STR <= UPX_RSIZE_MAX / 256)
|
||||||
|
ACC_COMPILE_TIME_ASSERT_HEADER(2ull * UPX_RSIZE_MAX * 9 / 8 + 16*1024*1024 < INT_MAX)
|
||||||
|
|
||||||
|
upx_rsize_t mem_size(upx_uint64_t element_size, upx_uint64_t n, upx_uint64_t extra1, upx_uint64_t extra2)
|
||||||
|
{
|
||||||
|
assert(element_size > 0);
|
||||||
|
if (element_size > UPX_RSIZE_MAX) throwCantPack("mem_size 1; take care");
|
||||||
|
if (n > UPX_RSIZE_MAX) throwCantPack("mem_size 2; take care");
|
||||||
|
if (extra1 > UPX_RSIZE_MAX) throwCantPack("mem_size 3; take care");
|
||||||
|
if (extra2 > UPX_RSIZE_MAX) throwCantPack("mem_size 4; take care");
|
||||||
|
upx_uint64_t bytes = element_size * n + extra1 + extra2; // cannot overflow
|
||||||
|
if (bytes > UPX_RSIZE_MAX) throwCantPack("mem_size 5; take care");
|
||||||
|
return ACC_ICONV(upx_rsize_t, bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
upx_rsize_t mem_size_get_n(upx_uint64_t element_size, upx_uint64_t n)
|
||||||
|
{
|
||||||
|
mem_size_assert(element_size, n);
|
||||||
|
return ACC_ICONV(upx_rsize_t, n); // return n
|
||||||
|
}
|
||||||
|
|
||||||
|
bool mem_size_valid(upx_uint64_t element_size, upx_uint64_t n, upx_uint64_t extra1, upx_uint64_t extra2)
|
||||||
|
{
|
||||||
|
assert(element_size > 0);
|
||||||
|
if (element_size > UPX_RSIZE_MAX) return false;
|
||||||
|
if (n > UPX_RSIZE_MAX) return false;
|
||||||
|
if (extra1 > UPX_RSIZE_MAX) return false;
|
||||||
|
if (extra2 > UPX_RSIZE_MAX) return false;
|
||||||
|
upx_uint64_t bytes = element_size * n + extra1 + extra2; // cannot overflow
|
||||||
|
if (bytes > UPX_RSIZE_MAX) return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool mem_size_valid_bytes(upx_uint64_t bytes)
|
||||||
|
{
|
||||||
|
if (bytes > UPX_RSIZE_MAX) return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int ptr_diff(const void *p1, const void *p2)
|
||||||
|
{
|
||||||
|
assert(p1 != NULL);
|
||||||
|
assert(p2 != NULL);
|
||||||
|
ptrdiff_t d = (const char *)p1 - (const char *)p2;
|
||||||
|
if (p1 >= p2)
|
||||||
|
assert(mem_size_valid_bytes(d));
|
||||||
|
else
|
||||||
|
assert(mem_size_valid_bytes(-d));
|
||||||
|
return ACC_ICONV(int, d);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned ptr_udiff(const void *p1, const void *p2)
|
||||||
|
{
|
||||||
|
int d = ptr_diff(p1, p2);
|
||||||
|
assert(d >= 0);
|
||||||
|
return ACC_ICONV(unsigned, d);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
/*************************************************************************
|
||||||
// bele.h
|
// bele.h
|
||||||
**************************************************************************/
|
**************************************************************************/
|
||||||
|
|
68
src/util.h
68
src/util.h
|
@ -28,6 +28,28 @@
|
||||||
#ifndef __UPX_UTIL_H
|
#ifndef __UPX_UTIL_H
|
||||||
#define __UPX_UTIL_H 1
|
#define __UPX_UTIL_H 1
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
// protect against integer overflows and malicious header fields
|
||||||
|
**************************************************************************/
|
||||||
|
|
||||||
|
#define New(type, n) new type[mem_size_get_n(sizeof(type), n)]
|
||||||
|
|
||||||
|
upx_rsize_t mem_size(upx_uint64_t element_size, upx_uint64_t n, upx_uint64_t extra1 = 0,
|
||||||
|
upx_uint64_t extra2 = 0);
|
||||||
|
upx_rsize_t mem_size_get_n(upx_uint64_t element_size, upx_uint64_t n);
|
||||||
|
|
||||||
|
inline void mem_size_assert(upx_uint64_t element_size, upx_uint64_t n, upx_uint64_t extra1 = 0,
|
||||||
|
upx_uint64_t extra2 = 0) {
|
||||||
|
(void) mem_size(element_size, n, extra1, extra2); // sanity check
|
||||||
|
}
|
||||||
|
|
||||||
|
bool mem_size_valid(upx_uint64_t element_size, upx_uint64_t n, upx_uint64_t extra1 = 0,
|
||||||
|
upx_uint64_t extra2 = 0);
|
||||||
|
bool mem_size_valid_bytes(upx_uint64_t bytes);
|
||||||
|
|
||||||
|
int ptr_diff(const void *p1, const void *p2);
|
||||||
|
unsigned ptr_udiff(const void *p1, const void *p2); // asserts p1 >= p2
|
||||||
|
|
||||||
/*************************************************************************
|
/*************************************************************************
|
||||||
// misc. support functions
|
// misc. support functions
|
||||||
**************************************************************************/
|
**************************************************************************/
|
||||||
|
@ -56,52 +78,6 @@ int find_le64(const void *b, int blen, upx_uint64_t what);
|
||||||
|
|
||||||
int mem_replace(void *b, int blen, const void *what, int wlen, const void *r);
|
int mem_replace(void *b, int blen, const void *what, int wlen, const void *r);
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
// protect against integer overflows and malicious header fields
|
|
||||||
**************************************************************************/
|
|
||||||
|
|
||||||
upx_rsize_t mem_size(upx_uint64_t element_size, upx_uint64_t n, upx_uint64_t extra1 = 0,
|
|
||||||
upx_uint64_t extra2 = 0);
|
|
||||||
upx_rsize_t mem_size_get_n(upx_uint64_t element_size, upx_uint64_t n);
|
|
||||||
|
|
||||||
inline void mem_size_assert(upx_uint64_t element_size, upx_uint64_t n, upx_uint64_t extra1 = 0,
|
|
||||||
upx_uint64_t extra2 = 0) {
|
|
||||||
(void) mem_size(element_size, n, extra1, extra2); // sanity check
|
|
||||||
}
|
|
||||||
|
|
||||||
bool mem_size_valid(upx_uint64_t element_size, upx_uint64_t n, upx_uint64_t extra1 = 0,
|
|
||||||
upx_uint64_t extra2 = 0);
|
|
||||||
bool mem_size_valid_bytes(upx_uint64_t bytes);
|
|
||||||
|
|
||||||
#define New(type, n) new type[mem_size_get_n(sizeof(type), n)]
|
|
||||||
|
|
||||||
int ptr_diff(const void *p1, const void *p2);
|
|
||||||
|
|
||||||
template <class T1, class T2>
|
|
||||||
inline unsigned ptr_udiff(const T1 &p1, const T2 &p2) {
|
|
||||||
int d = ptr_diff(p1, p2);
|
|
||||||
assert(d >= 0);
|
|
||||||
return ACC_ICONV(unsigned, d);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
// some unsigned char string support functions
|
|
||||||
**************************************************************************/
|
|
||||||
|
|
||||||
inline char *strcpy(unsigned char *s1, const unsigned char *s2) {
|
|
||||||
return strcpy((char *) s1, (const char *) s2);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline int strcmp(const unsigned char *s1, const unsigned char *s2) {
|
|
||||||
return strcmp((const char *) s1, (const char *) s2);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline int strcasecmp(const unsigned char *s1, const unsigned char *s2) {
|
|
||||||
return strcasecmp((const char *) s1, (const char *) s2);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline size_t strlen(const unsigned char *s) { return strlen((const char *) s); }
|
|
||||||
|
|
||||||
#endif /* already included */
|
#endif /* already included */
|
||||||
|
|
||||||
/* vim:set ts=4 sw=4 et: */
|
/* vim:set ts=4 sw=4 et: */
|
||||||
|
|
Loading…
Reference in New Issue
Block a user