1
0
mirror of https://github.com/upx/upx synced 2025-09-28 19:06:07 +08:00

Some refactoring. NFC.

This commit is contained in:
Markus F.X.J. Oberhumer 2016-10-09 13:23:19 +02:00
parent fab0c3b09d
commit b0207ce524
7 changed files with 129 additions and 127 deletions

View File

@ -631,7 +631,7 @@ struct upx_compress_result_t
// globals
**************************************************************************/
#include "snprintf.h"
#include "snprintf.h" // must get included first!
#include "stdcxx.h"
#include "options.h"
#include "except.h"

View File

@ -30,65 +30,6 @@
#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()
**************************************************************************/

View File

@ -614,7 +614,7 @@ class PeFile::ImportLinker : public ElfLinkerAMD64
unsigned len = 1 + 2 * strlen(dll) + 1 + 2 * strlen(proc) + 1 + 1;
tstr dlln(name_for_dll(dll, first_char));
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));
return procn;
}

View File

@ -745,35 +745,35 @@ static size_t dopr(char *buffer, size_t maxsize, const char *format, va_list arg
**************************************************************************/
// 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;
// preconditions
assert(count <= UPX_RSIZE_MAX_STR);
assert(max_size <= UPX_RSIZE_MAX_STR);
if (str != NULL)
assert(count > 0);
assert(max_size > 0);
else
assert(count == 0);
assert(max_size == 0);
size = dopr(str, count, format, ap);
size = dopr(str, max_size, format, ap);
// postconditions
assert(size > 0);
assert(size <= UPX_RSIZE_MAX_STR);
if (str != NULL) {
assert(size <= count);
assert(size <= max_size);
assert(str[size - 1] == '\0');
}
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;
int len;
va_start(ap, format);
len = upx_vsnprintf(str, count, format, ap);
len = upx_vsnprintf(str, max_size, format, ap);
va_end(ap);
return len;
}

View File

@ -28,31 +28,50 @@
#ifndef __UPX_SNPRINTF_H
#define __UPX_SNPRINTF_H 1
#ifdef __cplusplus
extern "C" {
#endif
/*************************************************************************
//
**************************************************************************/
int upx_vsnprintf(char *str, size_t count, const char *format, va_list ap);
int __acc_cdecl_va upx_snprintf (char *str, size_t count, const char *format, ...);
#ifdef __cplusplus
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 __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 *);
#undef strlen
#define strlen upx_strlen
#ifdef __cplusplus
}
#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 */
/* vim:set ts=4 sw=4 et: */

View File

@ -46,6 +46,72 @@
#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
**************************************************************************/

View File

@ -28,6 +28,28 @@
#ifndef __UPX_UTIL_H
#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
**************************************************************************/
@ -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);
/*************************************************************************
// 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 */
/* vim:set ts=4 sw=4 et: */