Modernize libc usage: stop using off_t, use modern printf.

C++ 14 is here, and old versions of MSVC and MSVCRT have
haunted us long enough.
This commit is contained in:
Markus F.X.J. Oberhumer 2021-01-05 18:52:05 +01:00
parent b4429e1a42
commit 700c8730cf
19 changed files with 130 additions and 1010 deletions

View File

@ -31,7 +31,6 @@
#if defined(__cplusplus)
# if (__cplusplus >= 201402L)
# elif defined(__GNUC__) && (__GNUC__+0 == 4) && (__cplusplus >= 201300L)
# elif defined(_MSC_VER) && defined(_MSVC_LANG) && (_MSVC_LANG+0 >= 201402L)
# else
# error "C++ 14 is required"
@ -43,6 +42,16 @@
#if !defined(_FILE_OFFSET_BITS)
# define _FILE_OFFSET_BITS 64
#endif
// MinGW <stdio.h> confusion
#if defined(_WIN32) && defined(__MINGW32__) && defined(__GNUC__)
# if !defined(_USE_MINGW_ANSI_STDIO)
# define _USE_MINGW_ANSI_STDIO 1
# endif
# if !defined(__printf__)
# define __printf__ __gnu_printf__
# endif
#endif
#undef NDEBUG
@ -179,6 +188,16 @@ typedef size_t upx_rsize_t;
#define UPX_RSIZE_MAX_MEM (768 * 1024 * 1024) // DO NOT CHANGE !!!
#define UPX_RSIZE_MAX_STR (1024 * 1024)
// using the system off_t was a bad idea even back in 199x...
typedef upx_int64_t upx_off_t;
#undef off_t
#if 0
// at some future point we can do this...
#define off_t DO_NOT_USE_off_t
#else
#define off_t upx_off_t
#endif
/*************************************************************************
// portab
@ -271,6 +290,15 @@ typedef size_t upx_rsize_t;
#define CLANG_FORMAT_DUMMY_STATEMENT /*empty*/
#if (ACC_CC_CLANG || ACC_CC_GNUC || ACC_CC_LLVM || ACC_CC_PATHSCALE)
__acc_static_forceinline void NO_printf(const char *, ...)
__attribute__((__format__(__printf__, 1, 2)));
__acc_static_forceinline void NO_fprintf(FILE *, const char *, ...)
__attribute__((__format__(__printf__, 2, 3)));
#endif
__acc_static_forceinline void NO_printf(const char *, ...) {}
__acc_static_forceinline void NO_fprintf(FILE *, const char *, ...) {}
#if !defined(__has_builtin)
# define __has_builtin(x) 0
#endif

View File

@ -124,7 +124,7 @@ console_t;
#if defined(__GNUC__)
void __acc_cdecl_va con_fprintf(FILE *f, const char *format, ...)
__attribute__((__format__(printf,2,3)));
__attribute__((__format__(__printf__,2,3)));
#else
void __acc_cdecl_va con_fprintf(FILE *f, const char *format, ...);
#endif

View File

@ -170,10 +170,9 @@ void FileBase::write(const void *buf, int len)
}
off_t FileBase::seek(upx_int64_t off64, int whence)
upx_off_t FileBase::seek(upx_off_t off, int whence)
{
mem_size_assert(1, off64 >= 0 ? off64 : -off64); // sanity check
off_t off = ACC_ICONV(off_t, off64);
mem_size_assert(1, off >= 0 ? off : -off); // sanity check
if (!isOpen())
throwIOException("bad seek 1");
if (whence == SEEK_SET) {
@ -193,24 +192,24 @@ off_t FileBase::seek(upx_int64_t off64, int whence)
}
off_t FileBase::tell() const
upx_off_t FileBase::tell() const
{
if (!isOpen())
throwIOException("bad tell");
off_t l = ::lseek(_fd, 0, SEEK_CUR);
upx_off_t l = ::lseek(_fd, 0, SEEK_CUR);
if (l < 0)
throwIOException("tell error",errno);
return l - _offset;
}
void FileBase::set_extent(off_t offset, off_t length)
void FileBase::set_extent(upx_off_t offset, upx_off_t length)
{
_offset = offset;
_length = length;
}
off_t FileBase::st_size() const
upx_off_t FileBase::st_size() const
{
return _length;
}
@ -289,21 +288,21 @@ int InputFile::readx(MemBuffer &buf, int len)
}
off_t InputFile::seek(upx_int64_t off64, int whence)
upx_off_t InputFile::seek(upx_off_t off, int whence)
{
off_t pos = super::seek(off64, whence);
upx_off_t pos = super::seek(off, whence);
if (_length < pos)
throwIOException("bad seek 4");
return pos;
}
off_t InputFile::tell() const
upx_off_t InputFile::tell() const
{
return super::tell();
}
off_t InputFile::st_size_orig() const
upx_off_t InputFile::st_size_orig() const
{
return _length_orig;
}
@ -373,7 +372,7 @@ void OutputFile::write(const void *buf, int len)
bytes_written += len;
}
off_t OutputFile::st_size() const
upx_off_t OutputFile::st_size() const
{
if (opt->to_stdout) { // might be a pipe ==> .st_size is invalid
return bytes_written; // too big if seek()+write() instead of rewrite()
@ -406,10 +405,9 @@ void OutputFile::rewrite(const void *buf, int len)
bytes_written -= len; // restore
}
off_t OutputFile::seek(upx_int64_t off64, int whence)
upx_off_t OutputFile::seek(upx_off_t off, int whence)
{
mem_size_assert(1, off64 >= 0 ? off64 : -off64); // sanity check
off_t off = ACC_ICONV(off_t, off64);
mem_size_assert(1, off >= 0 ? off : -off); // sanity check
assert(!opt->to_stdout);
switch (whence) {
case SEEK_SET: {
@ -436,20 +434,20 @@ off_t OutputFile::seek(upx_int64_t off64, int whence)
// return infile.read(buf, len);
//}
void OutputFile::set_extent(off_t offset, off_t length)
void OutputFile::set_extent(upx_off_t offset, upx_off_t length)
{
super::set_extent(offset, length);
bytes_written = 0;
if (0==offset && (off_t)~0u==length) {
if (0==offset && (upx_off_t)~0u==length) {
if (::fstat(_fd, &st) != 0)
throwIOException(_name, errno);
_length = st.st_size - offset;
}
}
off_t OutputFile::unset_extent()
upx_off_t OutputFile::unset_extent()
{
off_t l = ::lseek(_fd, 0, SEEK_END);
upx_off_t l = ::lseek(_fd, 0, SEEK_END);
if (l < 0)
throwIOException("lseek error", errno);
_offset = 0;

View File

@ -59,24 +59,24 @@ public:
virtual bool isOpen() const { return _fd >= 0; }
int getFd() const { return _fd; }
const char *getName() const { return _name; }
virtual off_t st_size() const; // { return _length; }
virtual void set_extent(off_t offset, off_t length);
virtual upx_off_t st_size() const; // { return _length; }
virtual void set_extent(upx_off_t offset, upx_off_t length);
protected:
bool do_sopen();
virtual int read(void *buf, int len);
virtual int readx(void *buf, int len);
virtual void write(const void *buf, int len);
virtual off_t seek(upx_int64_t off, int whence);
virtual off_t tell() const;
virtual upx_off_t seek(upx_off_t off, int whence);
virtual upx_off_t tell() const;
int _fd;
int _flags;
int _shflags;
int _mode;
const char *_name;
off_t _offset;
off_t _length;
upx_off_t _offset;
upx_off_t _length;
public:
struct stat st;
};
@ -106,11 +106,11 @@ public:
virtual int read(MemBuffer &buf, int len);
virtual int readx(MemBuffer &buf, int len);
virtual off_t seek(upx_int64_t off, int whence);
virtual off_t tell() const;
virtual off_t st_size_orig() const;
virtual upx_off_t seek(upx_off_t off, int whence);
virtual upx_off_t tell() const;
virtual upx_off_t st_size_orig() const;
protected:
off_t _length_orig;
upx_off_t _length_orig;
};
@ -135,21 +135,21 @@ public:
virtual void write(const void *buf, int len);
virtual void write(const MemBuffer *buf, int len);
virtual void write(const MemBuffer &buf, int len);
virtual void set_extent(off_t offset, off_t length);
virtual off_t unset_extent(); // returns actual length
virtual void set_extent(upx_off_t offset, upx_off_t length);
virtual upx_off_t unset_extent(); // returns actual length
off_t getBytesWritten() const { return bytes_written; }
virtual off_t st_size() const; // { return _length; }
upx_off_t getBytesWritten() const { return bytes_written; }
virtual upx_off_t st_size() const; // { return _length; }
// FIXME - these won't work when using the '--stdout' option
virtual off_t seek(upx_int64_t off, int whence);
virtual upx_off_t seek(upx_off_t off, int whence);
virtual void rewrite(const void *buf, int len);
// util
static void dump(const char *name, const void *buf, int len, int flags=-1);
protected:
off_t bytes_written;
upx_off_t bytes_written;
};
@ -172,13 +172,13 @@ public:
virtual void write(const void *buf, int len);
off_t getBytesWritten() const { return bytes_written; }
upx_off_t getBytesWritten() const { return bytes_written; }
protected:
upx_bytep b;
unsigned b_size;
unsigned b_pos;
off_t bytes_written;
upx_off_t bytes_written;
};
#endif /* if 0 */

View File

@ -45,7 +45,7 @@ static void __acc_cdecl_va internal_error(const char *format, ...) {
va_list ap;
va_start(ap, format);
vsnprintf(buf, sizeof(buf), format, ap);
upx_vsnprintf(buf, sizeof(buf), format, ap);
va_end(ap);
throwInternalError(buf);

View File

@ -1272,12 +1272,6 @@ void upx_compiler_sanity_check(void) {
COMPILE_TIME_ASSERT(sizeof(long) >= 4)
COMPILE_TIME_ASSERT(sizeof(void *) >= 4)
COMPILE_TIME_ASSERT(sizeof(off_t) >= sizeof(long))
COMPILE_TIME_ASSERT(((off_t) -1) < 0)
#if (ACC_OS_POSIX_DARWIN || ACC_OS_POSIX_LINUX)
COMPILE_TIME_ASSERT(sizeof(off_t) >= 8)
#endif
COMPILE_TIME_ASSERT(sizeof(BE16) == 2)
COMPILE_TIME_ASSERT(sizeof(BE32) == 4)
COMPILE_TIME_ASSERT(sizeof(BE64) == 8)
@ -1574,6 +1568,17 @@ int __acc_cdecl_main main(int argc, char *argv[]) {
// srand((int) time(nullptr));
srand((int) clock());
#if defined(_WIN32) || 1
// runtime check that Win32/MinGW <stdio.h> works as expected
{
long long ll = argc < 0 ? 0 : -1;
unsigned long long llu = (unsigned long long) ll;
char buf[256];
upx_snprintf(buf, sizeof(buf), ".%d.%ld.%lld.%u.%lu.%llu", -3, -2L, ll, 3U, 2LU, llu);
assert(strcmp(buf, ".-3.-2.-1.3.2.18446744073709551615") == 0);
}
#endif
int r = upx_main(argc, argv);
#if 0 && defined(__GLIBC__)

View File

@ -35,7 +35,7 @@
**************************************************************************/
#if defined(__SANITIZE_ADDRESS__)
__acc_static_forceinline bool use_simple_mcheck() { return false; }
__acc_static_forceinline constexpr bool use_simple_mcheck() { return false; }
#elif (WITH_VALGRIND) && defined(RUNNING_ON_VALGRIND)
static int use_simple_mcheck_flag = -1;
__acc_static_noinline void use_simple_mcheck_init()

View File

@ -3841,8 +3841,8 @@ ACC_COMPILE_TIME_ASSERT_HEADER(sizeof(acc_int_fast64_t) == sizeof(acc_uint_fast6
# undef HAVE_SNPRINTF
# undef HAVE_VSNPRINTF
# else
# define snprintf _snprintf
# define vsnprintf _vsnprintf
//# define snprintf _snprintf
//# define vsnprintf _vsnprintf
# endif
#elif (ACC_OS_WIN32 && ACC_LIBC_MSL)
# if (__MSL__ < 0x8000ul)

View File

@ -223,7 +223,7 @@ int PackCom::canUnpack()
{
if (!readPackHeader(128))
return false;
if (file_size <= (off_t) ph.c_len)
if (file_size_u <= ph.c_len)
return false;
return true;
}
@ -243,8 +243,8 @@ void PackCom::unpack(OutputFile *fo)
fi->readx(ibuf,file_size);
// get compressed data offset
int e_len = ph.buf_offset + ph.getPackHeaderSize();
if (file_size <= e_len + (off_t)ph.c_len)
unsigned e_len = ph.buf_offset + ph.getPackHeaderSize();
if (file_size_u <= e_len + ph.c_len)
throwCantUnpack("file damaged");
// decompress

View File

@ -161,24 +161,25 @@ static bool is_dlm(InputFile *fi, unsigned coff_offset)
static void handle_allegropak(InputFile *fi, OutputFile *fo)
{
unsigned char buf[0x4000];
unsigned char b[8];
int pfsize = 0;
try {
fi->seek(-8, SEEK_END);
fi->readx(buf, 8);
if (memcmp(buf, "slh+", 4) != 0)
fi->readx(b, 8);
if (memcmp(b, "slh+", 4) != 0)
return;
pfsize = get_be32_signed(buf+4);
if (pfsize <= 8 || pfsize >= (off_t) fi->st.st_size)
pfsize = get_be32_signed(b+4);
if (pfsize <= 8 || pfsize >= fi->st.st_size)
return;
fi->seek(-(off_t)pfsize, SEEK_END);
fi->seek(-pfsize, SEEK_END);
} catch (const IOException&) {
return;
}
MemBuffer buf(0x4000);
while (pfsize > 0)
{
const int len = UPX_MIN(pfsize, (int)sizeof(buf));
const int len = UPX_MIN(pfsize, (int)buf.getSize());
fi->readx(buf, len);
fo->write(buf, len);
pfsize -= len;

View File

@ -286,10 +286,10 @@ int PackExe::readFileHeader()
}
ih_imagesize = ih_exesize - ih.headsize16*16;
ih_overlay = file_size - ih_exesize;
if (file_size < (int)sizeof(ih)
if (file_size_u < sizeof(ih)
|| ((ih.m512 | ih.p512) && ih.m512+ih.p512*512u < sizeof (ih)))
throwCantPack("illegal exe header");
if (file_size < (off_t)ih_exesize || ih_imagesize <= 0 || ih_imagesize > ih_exesize)
if (file_size_u < ih_exesize || ih_imagesize <= 0 || ih_imagesize > ih_exesize)
throwCantPack("exe header corrupted");
#if 0
printf("dos/exe header: %d %d %d\n", ih_exesize, ih_imagesize, ih_overlay);
@ -674,10 +674,10 @@ int PackExe::canUnpack()
{
if (!readFileHeader())
return false;
const off_t off = ih.headsize16 * 16;
const unsigned off = ih.headsize16 * 16;
fi->seek(off, SEEK_SET);
bool b = readPackHeader(4096);
return b && (off + (off_t) ph.c_len <= file_size);
return b && (off + ph.c_len <= file_size_u);
}

View File

@ -273,7 +273,7 @@ bool PackPs1::canPack()
throwCantPack("unsupported header flags (try --force)");
if (!opt->force && file_size < PS_MIN_SIZE)
throwCantPack("file is too small (try --force)");
if (!opt->force && file_size > (off_t) PS_MAX_SIZE)
if (!opt->force && file_size_u > PS_MAX_SIZE)
throwCantPack("file is too big (try --force)");
return true;
}

View File

@ -116,7 +116,7 @@ int PackVmlinuzI386::readFileHeader()
return 0;
int format = UPX_F_VMLINUZ_i386;
unsigned sys_size = ALIGN_UP((unsigned) file_size, 16u) - setup_size;
unsigned sys_size = ALIGN_UP((unsigned) file_size_u, 16u) - setup_size;
const unsigned char *p = (const unsigned char *) &h + 0x1e3;
@ -234,7 +234,7 @@ int PackVmlinuzI386::decompressKernel()
}
}
checkAlreadyPacked(obuf + setup_size, UPX_MIN(file_size - setup_size, (off_t)1024));
checkAlreadyPacked(obuf + setup_size, UPX_MIN(file_size - setup_size, 1024LL));
int gzoff = setup_size;
if (0x208<=h.version) {
@ -259,7 +259,7 @@ int PackVmlinuzI386::decompressKernel()
// try to decompress
int klen;
int fd;
off_t fd_pos;
upx_off_t fd_pos;
for (;;)
{
klen = -1;
@ -344,7 +344,7 @@ int PackVmlinuzI386::decompressKernel()
// some checks
if (fd_pos != file_size)
{
//printf("fd_pos: %ld, file_size: %ld\n", (long)fd_pos, (long)file_size);
NO_printf("fd_pos: %lld, file_size: %lld\n", fd_pos, file_size);
// linux-2.6.21.5/arch/i386/boot/compressed/vmlinux.lds
// puts .data.compressed ahead of .text, .rodata, etc;
@ -759,7 +759,7 @@ int PackVmlinuzARMEL::decompressKernel()
fi->seek(0, SEEK_SET);
fi->readx(obuf, file_size);
//checkAlreadyPacked(obuf + setup_size, UPX_MIN(file_size - setup_size, (off_t)1024));
//checkAlreadyPacked(obuf + setup_size, UPX_MIN(file_size - setup_size, 1024LL));
// Find head.S:
// bl decompress_kernel # 0xeb......
@ -841,7 +841,7 @@ int PackVmlinuzARMEL::decompressKernel()
// try to decompress
int klen;
int fd;
off_t fd_pos;
upx_off_t fd_pos;
for (;;)
{
klen = -1;

View File

@ -39,8 +39,10 @@
Packer::Packer(InputFile *f)
: bele(nullptr), fi(f), file_size(-1), ph_format(-1), ph_version(-1), uip(nullptr),
linker(nullptr), last_patch(nullptr), last_patch_len(0), last_patch_off(0) {
file_size = 0;
if (fi != nullptr)
file_size = fi->st_size();
mem_size_assert(1, file_size_u);
uip = new UiPacker(this);
mem_clear(&ph, sizeof(ph));
}
@ -504,7 +506,7 @@ void Packer::handleStub(InputFile *fif, OutputFile *fo, unsigned size) {
}
void Packer::checkOverlay(unsigned overlay) {
if ((int) overlay < 0 || (off_t) overlay > file_size)
if ((int) overlay < 0 || overlay > file_size_u)
throw OverlayException("invalid overlay size; file is possibly corrupt");
if (overlay == 0)
return;
@ -515,7 +517,7 @@ void Packer::checkOverlay(unsigned overlay) {
void Packer::copyOverlay(OutputFile *fo, unsigned overlay, MemBuffer *buf, bool do_seek) {
assert((int) overlay >= 0);
assert((off_t) overlay < file_size);
assert(overlay < file_size_u);
buf->checkState();
if (!fo || overlay == 0)
return;
@ -526,7 +528,7 @@ void Packer::copyOverlay(OutputFile *fo, unsigned overlay, MemBuffer *buf, bool
}
info("Copying overlay: %d bytes", overlay);
if (do_seek)
fi->seek(-(off_t) overlay, SEEK_END);
fi->seek(-(upx_off_t) overlay, SEEK_END);
// get buffer size, align to improve i/o speed
unsigned buf_size = buf->getSize();
@ -640,9 +642,9 @@ bool Packer::getPackHeader(void *b, int blen, bool allow_incompressible) {
return false;
if (ph.c_len > ph.u_len || (ph.c_len == ph.u_len && !allow_incompressible) ||
(off_t) ph.c_len >= file_size || ph.version <= 0 || ph.version >= 0xff)
ph.c_len >= file_size_u || ph.version <= 0 || ph.version >= 0xff)
throwCantUnpack("header corrupted");
else if ((off_t) ph.u_len > ph.u_file_size) {
else if (ph.u_len > ph.u_file_size) {
#if 0
// FIXME: does this check make sense w.r.t. overlays ???
if (ph.format == UPX_F_WIN32_PE || ph.format == UPX_F_DOS_EXE)

View File

@ -66,7 +66,7 @@ public:
unsigned c_len;
unsigned u_adler;
unsigned c_adler;
off_t u_file_size;
unsigned u_file_size;
int filter;
int filter_cto;
int n_mru; // FIXME: rename to filter_misc
@ -291,8 +291,13 @@ protected:
protected:
const N_BELE_RTP::AbstractPolicy *bele = nullptr; // target endianness
InputFile *fi = nullptr;
off_t file_size; // will get set by constructor
PackHeader ph; // must be filled by canUnpack()
union { // unnamed union
upx_int64_t file_size; // will get set by constructor
upx_uint64_t file_size_u; // explicitly unsigned
};
PackHeader ph; // must be filled by canUnpack()
int ph_format;
int ph_version;

View File

@ -2094,7 +2094,7 @@ void PeFile::readSectionHeaders(unsigned objs, unsigned sizeof_ih)
}
mb_isection.alloc(sizeof(pe_section_t) * objs);
isection = (pe_section_t *)mb_isection.getVoidPtr();
if (file_size < (off_t)(pe_offset + sizeof_ih + sizeof(pe_section_t)*objs)) {
if (file_size_u < pe_offset + sizeof_ih + sizeof(pe_section_t)*objs) {
char buf[32]; snprintf(buf, sizeof(buf), "too many sections %d", objs);
throwCantPack(buf);
}

View File

@ -1,776 +1,9 @@
/*
* Copyright Patrick Powell 1995
* This code is based on code written by Patrick Powell (papowell@astart.com)
* It may be used for any purpose as long as this notice remains intact
* on all source code distributions
*/
/**************************************************************
* Original:
* Patrick Powell Tue Apr 11 09:48:21 PDT 1995
* A bombproof version of doprnt (dopr) included.
* Sigh. This sort of thing is always nasty do deal with. Note that
* the version here does not include floating point...
*
* snprintf() is used instead of sprintf() as it does limit checks
* for string length. This covers a nasty loophole.
*
* The other functions are there to prevent NULL pointers from
* causing nast effects.
*
* More Recently:
* Brandon Long <blong@fiction.net> 9/15/96 for mutt 0.43
* This was ugly. It is still ugly. I opted out of floating point
* numbers, but the formatter understands just about everything
* from the normal C string format, at least as far as I can tell from
* the Solaris 2.5 printf(3S) man page.
*
* Brandon Long <blong@fiction.net> 10/22/97 for mutt 0.87.1
* Ok, added some minimal floating point support, which means this
* probably requires libm on most operating systems. Don't yet
* support the exponent (e,E) and sigfig (g,G). Also, fmtint()
* was pretty badly broken, it just wasn't being exercised in ways
* which showed it, so that's been fixed. Also, formated the code
* to mutt conventions, and removed dead code left over from the
* original. Also, there is now a builtin-test, just compile with:
* gcc -DTEST_SNPRINTF -o snprintf snprintf.c -lm
* and run snprintf for results.
*
* Thomas Roessler <roessler@guug.de> 01/27/98 for mutt 0.89i
* The PGP code was using unsigned hexadecimal formats.
* Unfortunately, unsigned formats simply didn't work.
*
* Michael Elkins <me@cs.hmc.edu> 03/05/98 for mutt 0.90.8
* The original code assumed that both snprintf() and vsnprintf() were
* missing. Some systems only have snprintf() but not vsnprintf(), so
* the code is now broken down under HAVE_SNPRINTF and HAVE_VSNPRINTF.
*
* Andrew Tridgell (tridge@samba.org) Oct 1998
* fixed handling of %.0f
* added test for HAVE_LONG_DOUBLE
*
* tridge@samba.org, idra@samba.org, April 2001
* got rid of fcvt code (twas buggy and made testing harder)
* added C99 semantics
*
* markus@oberhumer.com, August 2002
* large modifications for use in UPX
*
**************************************************************/
#if 1
#include "conf.h"
#else
#include <ctype.h>
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
#undef NDEBUG
#include <assert.h>
#endif
#undef LLONG
#undef ULLONG
#define LLONG upx_int64_t
#define ULLONG upx_uint64_t
#undef NO_FLOAT
#undef LDOUBLE
#if 1
#define NO_FLOAT 1
#define float error no_float
#define double error no_float
#else
#if (HAVE_LONG_DOUBLE)
#define LDOUBLE long double
#else
#define LDOUBLE double
#endif
#endif
/*
* dopr(): poor man's version of doprintf
*/
/* format read states */
#define DP_S_DEFAULT 0
#define DP_S_FLAGS 1
#define DP_S_MIN 2
#define DP_S_DOT 3
#define DP_S_MAX 4
#define DP_S_MOD 5
#define DP_S_CONV 6
#define DP_S_DONE 7
/* format flags - Bits */
#define DP_F_MINUS (1 << 0)
#define DP_F_PLUS (1 << 1)
#define DP_F_SPACE (1 << 2)
#define DP_F_NUM (1 << 3)
#define DP_F_ZERO (1 << 4)
#define DP_F_UP (1 << 5)
#define DP_F_UNSIGNED (1 << 6)
/* Length modifier */
#define DP_C_CHAR 1
#define DP_C_SHORT 2
#define DP_C_LONG 3
#define DP_C_LLONG 4
#define DP_C_LDOUBLE 5
#define char_to_int(p) ((p) - '0')
#undef MAX
#define MAX(p, q) (((p) >= (q)) ? (p) : (q))
/*************************************************************************
//
// UPX version of string functions, with assertions
**************************************************************************/
__acc_static_forceinline void dopr_outch(char *buffer, size_t *currsize, size_t maxsize, int c) {
if (*currsize < maxsize)
buffer[*currsize] = (char) c;
*currsize += 1;
}
static void fmtstr(char *buffer, size_t *currsize, size_t maxsize, const char *strvalue, int strln,
int flags, int min, int max) {
int padlen; /* amount to pad */
int cnt = 0;
#ifdef DEBUG_SNPRINTF
printf("fmtstr min=%d max=%d s=[%s]\n", min, max, strvalue);
#endif
assert(strvalue != nullptr);
padlen = min - strln;
if (padlen < 0)
padlen = 0;
if (flags & DP_F_MINUS)
padlen = -padlen; /* Left Justify */
while (cnt < max && padlen > 0) {
dopr_outch(buffer, currsize, maxsize, ' ');
--padlen;
++cnt;
}
while (cnt < max && *strvalue) {
dopr_outch(buffer, currsize, maxsize, *strvalue);
++strvalue;
++cnt;
}
while (cnt < max && padlen < 0) {
dopr_outch(buffer, currsize, maxsize, ' ');
++padlen;
++cnt;
}
}
/* Have to handle DP_F_NUM (ie 0x and 0 alternates) */
static void fmtint(char *buffer, size_t *currsize, size_t maxsize, LLONG value, unsigned base,
int min, int max, int flags) {
int signvalue = 0;
ULLONG uvalue;
char convert[64 + 1];
int place = 0;
int spadlen = 0; /* amount to space pad */
int zpadlen = 0; /* amount to zero pad */
const char *digits;
if (min < 0)
min = 0;
if (max < 0)
max = 0;
uvalue = value;
if (!(flags & DP_F_UNSIGNED)) {
if (value < 0) {
signvalue = '-';
uvalue = -value;
} else {
if (flags & DP_F_PLUS) /* Do a sign (+/i) */
signvalue = '+';
else if (flags & DP_F_SPACE)
signvalue = ' ';
}
}
digits = (flags & DP_F_UP) ? "0123456789ABCDEF" : "0123456789abcdef";
do {
convert[place] = digits[(unsigned) (uvalue % base)];
uvalue /= base;
} while (++place < (int) sizeof(convert) - 1 && uvalue);
convert[place] = 0;
zpadlen = max - place;
spadlen = min - MAX(max, place) - (signvalue ? 1 : 0);
if (zpadlen < 0)
zpadlen = 0;
if (spadlen < 0)
spadlen = 0;
if (flags & DP_F_ZERO) {
zpadlen = MAX(zpadlen, spadlen);
spadlen = 0;
}
if (flags & DP_F_MINUS)
spadlen = -spadlen; /* Left Justifty */
#ifdef DEBUG_SNPRINTF
printf("zpad: %d, spad: %d, min: %d, max: %d, place: %d\n", zpadlen, spadlen, min, max, place);
#endif
/* Spaces */
while (spadlen > 0) {
dopr_outch(buffer, currsize, maxsize, ' ');
--spadlen;
}
/* Sign */
if (signvalue)
dopr_outch(buffer, currsize, maxsize, signvalue);
/* Zeros */
while (zpadlen > 0) {
dopr_outch(buffer, currsize, maxsize, '0');
--zpadlen;
}
/* Digits */
while (place > 0)
dopr_outch(buffer, currsize, maxsize, convert[--place]);
/* Left Justified spaces */
while (spadlen < 0) {
dopr_outch(buffer, currsize, maxsize, ' ');
++spadlen;
}
}
/*************************************************************************
// floating format support
**************************************************************************/
#if !(NO_FLOAT)
static LDOUBLE abs_val(LDOUBLE value) {
LDOUBLE result = value;
if (value < 0)
result = -value;
return result;
}
static LDOUBLE POW10(int exp) {
LDOUBLE result = 1;
while (exp) {
result *= 10;
exp--;
}
return result;
}
static LLONG ROUND(LDOUBLE value) {
LLONG intpart;
intpart = (LLONG) value;
value = value - intpart;
if (value >= 0.5)
intpart++;
return intpart;
}
/* a replacement for modf that doesn't need the math library. Should
be portable, but slow */
static double my_modf(double x0, double *iptr) {
int i;
long l;
double x = x0;
double f = 1.0;
for (i = 0; i < 100; i++) {
l = (long) x;
if (l <= (x + 1) && l >= (x - 1))
break;
x *= 0.1;
f *= 10.0;
}
if (i == 100) {
/* yikes! the number is beyond what we can handle. What do we do? */
*iptr = 0.0;
return 0;
}
if (i != 0) {
double i2, ret;
ret = my_modf(x0 - l * f, &i2);
*iptr = l * f + i2;
return ret;
}
*iptr = l;
return x - *iptr;
}
static void fmtfp(char *buffer, size_t *currsize, size_t maxsize, LDOUBLE fvalue, int min, int max,
int flags) {
/* avoid warnings with 'gcc -Wshadow' */
#undef index
#define index fmtfp_index
int signvalue = 0;
double ufvalue;
char iconvert[311 + 1];
char fconvert[311 + 1];
int iplace = 0;
int fplace = 0;
int padlen = 0; /* amount to pad */
int zpadlen = 0;
const char *digits;
int index;
double intpart;
double fracpart;
double temp;
/*
* AIX manpage says the default is 0, but Solaris says the default
* is 6, and sprintf on AIX defaults to 6
*/
if (min < 0)
min = 0;
if (max < 0)
max = 6;
ufvalue = abs_val(fvalue);
if (fvalue < 0) {
signvalue = '-';
} else {
if (flags & DP_F_PLUS) { /* Do a sign (+/i) */
signvalue = '+';
} else {
if (flags & DP_F_SPACE)
signvalue = ' ';
}
}
digits = "0123456789ABCDEF";
#if 0
digits = (flags & DP_F_UP) ? "0123456789ABCDEF" : "0123456789abcdef";
#endif
#if 0
if (max == 0) ufvalue += 0.5; /* if max = 0 we must round */
#endif
/*
* Sorry, we only support 16 digits past the decimal because of our
* conversion method
*/
if (max > 16)
max = 16;
/* We "cheat" by converting the fractional part to integer by
* multiplying by a factor of 10
*/
temp = ufvalue;
my_modf(temp, &intpart);
fracpart = ROUND((POW10(max)) * (ufvalue - intpart));
if (fracpart >= POW10(max)) {
intpart++;
fracpart -= POW10(max);
}
/* Convert integer part */
do {
temp = intpart;
my_modf(intpart * 0.1, &intpart);
temp = temp * 0.1;
index = (int) ((temp - intpart + 0.05) * 10.0);
/* index = (int) (((double)(temp*0.1) -intpart +0.05) *10.0); */
/* printf ("%llf, %f, %x\n", temp, intpart, index); */
iconvert[iplace] = digits[index];
} while (++iplace < (int) sizeof(iconvert) - 1 && intpart);
iconvert[iplace] = 0;
/* Convert fractional part */
if (fracpart) {
do {
temp = fracpart;
my_modf(fracpart * 0.1, &fracpart);
temp = temp * 0.1;
index = (int) ((temp - fracpart + 0.05) * 10.0);
/* index = (int) ((((temp/10) -fracpart) +0.05) *10); */
/* printf ("%lf, %lf, %ld\n", temp, fracpart, index); */
fconvert[fplace] = digits[index];
} while (++fplace < (int) sizeof(fconvert) - 1 && fracpart);
}
fconvert[fplace] = 0;
/* -1 for decimal point, another -1 if we are printing a sign */
padlen = min - iplace - max - 1 - ((signvalue) ? 1 : 0);
zpadlen = max - fplace;
if (zpadlen < 0)
zpadlen = 0;
if (padlen < 0)
padlen = 0;
if (flags & DP_F_MINUS)
padlen = -padlen; /* Left Justifty */
if ((flags & DP_F_ZERO) && (padlen > 0)) {
if (signvalue) {
dopr_outch(buffer, currsize, maxsize, signvalue);
--padlen;
signvalue = 0;
}
while (padlen > 0) {
dopr_outch(buffer, currsize, maxsize, '0');
--padlen;
}
}
while (padlen > 0) {
dopr_outch(buffer, currsize, maxsize, ' ');
--padlen;
}
if (signvalue)
dopr_outch(buffer, currsize, maxsize, signvalue);
while (iplace > 0)
dopr_outch(buffer, currsize, maxsize, iconvert[--iplace]);
#ifdef DEBUG_SNPRINTF
printf("fmtfp: fplace=%d zpadlen=%d\n", fplace, zpadlen);
#endif
/*
* Decimal point. This should probably use locale to find the correct
* char to print out.
*/
if (max > 0) {
dopr_outch(buffer, currsize, maxsize, '.');
while (fplace > 0)
dopr_outch(buffer, currsize, maxsize, fconvert[--fplace]);
}
while (zpadlen > 0) {
dopr_outch(buffer, currsize, maxsize, '0');
--zpadlen;
}
while (padlen < 0) {
dopr_outch(buffer, currsize, maxsize, ' ');
++padlen;
}
#undef index
}
#endif /* !(NO_FLOAT) */
/*************************************************************************
// dopr()
**************************************************************************/
static size_t dopr(char *buffer, size_t maxsize, const char *format, va_list args) {
char ch;
LLONG value;
#if !(NO_FLOAT)
LDOUBLE fvalue;
#endif
int min;
int max;
int state;
int flags;
int cflags;
size_t currsize;
state = DP_S_DEFAULT;
currsize = flags = cflags = min = 0;
max = -1;
ch = *format++;
while (state != DP_S_DONE) {
unsigned base;
const char *strvalue;
int strln;
if (ch == '\0')
state = DP_S_DONE;
switch (state) {
case DP_S_DEFAULT:
if (ch == '%')
state = DP_S_FLAGS;
else
dopr_outch(buffer, &currsize, maxsize, ch);
ch = *format++;
break;
case DP_S_FLAGS:
switch (ch) {
case '-':
flags |= DP_F_MINUS;
ch = *format++;
break;
case '+':
flags |= DP_F_PLUS;
ch = *format++;
break;
case ' ':
flags |= DP_F_SPACE;
ch = *format++;
break;
case '#':
flags |= DP_F_NUM;
ch = *format++;
break;
case '0':
flags |= DP_F_ZERO;
ch = *format++;
break;
default:
state = DP_S_MIN;
break;
}
break;
case DP_S_MIN:
if (isdigit((unsigned char) ch)) {
min = 10 * min + char_to_int(ch);
ch = *format++;
} else if (ch == '*') {
min = va_arg(args, int);
ch = *format++;
state = DP_S_DOT;
} else {
state = DP_S_DOT;
}
assert(min > 0 - UPX_RSIZE_MAX_STR);
assert(min < UPX_RSIZE_MAX_STR);
break;
case DP_S_DOT:
if (ch == '.') {
state = DP_S_MAX;
ch = *format++;
} else {
state = DP_S_MOD;
}
break;
case DP_S_MAX:
if (isdigit((unsigned char) ch)) {
if (max < 0)
max = 0;
max = 10 * max + char_to_int(ch);
ch = *format++;
} else if (ch == '*') {
max = va_arg(args, int);
ch = *format++;
state = DP_S_MOD;
} else {
state = DP_S_MOD;
}
assert(max > 0 - UPX_RSIZE_MAX_STR);
assert(max < UPX_RSIZE_MAX_STR);
break;
case DP_S_MOD:
switch (ch) {
case 'h':
cflags = DP_C_SHORT;
ch = *format++;
if (ch == 'h') {
cflags = DP_C_CHAR;
ch = *format++;
}
break;
case 'l':
cflags = DP_C_LONG;
ch = *format++;
if (ch == 'l') {
cflags = DP_C_LLONG;
ch = *format++;
}
break;
case 'j': // intmax_t
cflags = DP_C_LLONG;
ch = *format++;
break;
case 'z': // size_t
cflags = sizeof(size_t) == sizeof(LLONG) ? DP_C_LLONG : 0;
ch = *format++;
break;
case 't': // ptrdiff_t
cflags = sizeof(ptrdiff_t) == sizeof(LLONG) ? DP_C_LLONG : 0;
ch = *format++;
break;
case 'L':
cflags = DP_C_LDOUBLE;
ch = *format++;
break;
default:
break;
}
state = DP_S_CONV;
break;
case DP_S_CONV:
switch (ch) {
case 'd':
case 'i':
if (cflags == DP_C_CHAR)
value = (LLONG)(signed char) va_arg(args, int);
else if (cflags == DP_C_SHORT)
value = (LLONG)(short) va_arg(args, int);
else if (cflags == DP_C_LONG)
value = (LLONG) va_arg(args, long);
else if (cflags == DP_C_LLONG)
value = (LLONG) va_arg(args, LLONG);
else
value = (LLONG) va_arg(args, int);
fmtint(buffer, &currsize, maxsize, value, 10, min, max, flags);
break;
case 'X':
flags |= DP_F_UP;
/*fallthrough*/
case 'x':
base = 16;
l_fmtuint:
flags |= DP_F_UNSIGNED;
if (cflags == DP_C_CHAR)
value = (ULLONG)(unsigned char) va_arg(args, unsigned);
else if (cflags == DP_C_SHORT)
value = (ULLONG)(unsigned short) va_arg(args, unsigned);
else if (cflags == DP_C_LONG)
value = (ULLONG) va_arg(args, unsigned long);
else if (cflags == DP_C_LLONG)
value = (ULLONG) va_arg(args, ULLONG);
else
value = (ULLONG) va_arg(args, unsigned);
fmtint(buffer, &currsize, maxsize, value, base, min, max, flags);
break;
case 'u':
base = 10;
goto l_fmtuint;
case 'o':
base = 8;
goto l_fmtuint;
case 'c':
// TODO: wint_t
dopr_outch(buffer, &currsize, maxsize, va_arg(args, int));
break;
case 's':
// TODO: wchar_t
strvalue = va_arg(args, const char *);
if (!strvalue)
strvalue = "(NULL)";
strln = (int) strlen(strvalue);
if (max == -1)
max = strln;
if (min > 0 && max >= 0 && min > max)
max = min;
fmtstr(buffer, &currsize, maxsize, strvalue, strln, flags, min, max);
break;
case 'p':
strvalue = (const char *) va_arg(args, const void *);
fmtint(buffer, &currsize, maxsize, (LLONG)(upx_uintptr_t) strvalue, 16, min, max,
flags);
break;
case 'n':
if (cflags == DP_C_CHAR) {
signed char *num;
num = va_arg(args, signed char *);
assert(num != nullptr);
*num = (signed char) currsize;
} else if (cflags == DP_C_SHORT) {
short *num;
num = va_arg(args, short *);
assert(num != nullptr);
*num = (short) currsize;
} else if (cflags == DP_C_LONG) {
long *num;
num = va_arg(args, long *);
assert(num != nullptr);
*num = (long) currsize;
} else if (cflags == DP_C_LLONG) {
LLONG *num;
num = va_arg(args, LLONG *);
assert(num != nullptr);
*num = (LLONG) currsize;
} else {
int *num;
num = va_arg(args, int *);
assert(num != nullptr);
*num = (int) currsize;
}
break;
case '%':
dopr_outch(buffer, &currsize, maxsize, ch);
break;
#if !(NO_FLOAT)
case 'F':
flags |= DP_F_UP;
/*fallthrough*/
case 'f':
if (cflags == DP_C_LDOUBLE)
fvalue = va_arg(args, LDOUBLE);
else
fvalue = va_arg(args, double);
/* um, floating point? */
fmtfp(buffer, &currsize, maxsize, fvalue, min, max, flags);
break;
case 'E':
flags |= DP_F_UP;
/*fallthrough*/
case 'e':
if (cflags == DP_C_LDOUBLE)
fvalue = va_arg(args, LDOUBLE);
else
fvalue = va_arg(args, double);
break;
case 'G':
flags |= DP_F_UP;
/*fallthrough*/
case 'g':
if (cflags == DP_C_LDOUBLE)
fvalue = va_arg(args, LDOUBLE);
else
fvalue = va_arg(args, double);
break;
#else
case 'F':
case 'f':
case 'E':
case 'e':
case 'G':
case 'g':
case 'A':
case 'a':
assert(0);
exit(255);
#endif /* !(NO_FLOAT) */
default:
/* Unknown, skip */
break;
}
ch = *format++;
state = DP_S_DEFAULT;
flags = cflags = min = 0;
max = -1;
break;
case DP_S_DONE:
break;
default:
/* hmm? */
break; /* some picky compilers need this */
}
}
dopr_outch(buffer, &currsize, maxsize, '\0');
return currsize; // returns size, not length
}
/*************************************************************************
// public entries
**************************************************************************/
// UPX version with assertions
int upx_vsnprintf(char *str, upx_rsize_t max_size, const char *format, va_list ap) {
size_t size;
@ -781,7 +14,10 @@ int upx_vsnprintf(char *str, upx_rsize_t max_size, const char *format, va_list a
else
assert(max_size == 0);
size = dopr(str, max_size, format, ap);
long long n = vsnprintf(str, max_size, format, ap);
assert(n >= 0);
assert(n < UPX_RSIZE_MAX_STR);
size = (size_t)n + 1;
// postconditions
assert(size > 0);
@ -809,14 +45,12 @@ int upx_vasprintf(char **ptr, const char *format, va_list ap) {
assert(ptr != nullptr);
*ptr = nullptr;
#if defined(va_copy)
va_list ap_copy;
va_copy(ap_copy, ap);
len = upx_vsnprintf(nullptr, 0, format, ap_copy);
va_end(ap_copy);
#else
len = upx_vsnprintf(nullptr, 0, format, ap);
#endif
if (len >= 0) {
*ptr = (char *) malloc(len + 1);
assert(*ptr != nullptr);
@ -846,152 +80,5 @@ upx_rsize_t upx_strlen(const char *s) {
return len;
}
/*************************************************************************
//
**************************************************************************/
#if 0 || defined(TEST_SNPRINTF)
#undef sprintf
#include <stdio.h>
#include <string.h>
#include <math.h>
#undef snprintf
#define snprintf upx_snprintf
//int sprintf(char *str,const char *fmt,...);
int main(void)
{
char buf1[1024];
char buf2[1024];
const char *fp_fmt[] = {
"%1.1f",
"%-1.5f",
"%1.5f",
"%123.9f",
"%10.5f",
"% 10.5f",
"%+22.9f",
"%+4.9f",
"%01.3f",
"%4f",
"%3.1f",
"%3.2f",
"%.0f",
"%f",
"-16.16f",
nullptr
};
const double fp_nums[] = {
6442452944.1234, -1.5, 134.21, 91340.2, 341.1234, 0203.9, 0.96, 0.996,
0.9996, 1.996, 4.136, 0
};
const char *int_fmt[] = {
"%-1.5d",
"%1.5d",
"%123.9d",
"%5.5d",
"%10.5d",
"% 10.5d",
"%+22.33d",
"%01.3d",
"%4d",
"%d",
nullptr
};
const int int_nums[] = { -1, 134, 91340, 341, 0203, 0 };
const char *str_fmt[] = {
"10.5s",
"5.10s",
"10.1s",
"0.10s",
"10.0s",
"1.10s",
"%s",
"%.1s",
"%.10s",
"%10s",
0
};
const char *str_vals[] = {"hello", "a", "", "a longer string", nullptr};
int x, y;
int fail = 0;
int num = 0;
printf ("Testing snprintf format codes against system sprintf...\n");
for (x = 0; fp_fmt[x] ; x++) {
for (y = 0; fp_nums[y] != 0 ; y++) {
int l1 = snprintf(nullptr, 0, fp_fmt[x], fp_nums[y]);
int l2 = snprintf(buf1, sizeof(buf1), fp_fmt[x], fp_nums[y]);
sprintf (buf2, fp_fmt[x], fp_nums[y]);
if (strcmp (buf1, buf2)) {
printf("snprintf doesn't match Format: %s\n\tsnprintf = [%s]\n\t sprintf = [%s]\n",
fp_fmt[x], buf1, buf2);
fail++;
}
if (l1 != l2) {
printf("snprintf l1 != l2 (%d %d) %s\n", l1, l2, fp_fmt[x]);
fail++;
}
num++;
}
}
for (x = 0; int_fmt[x] ; x++) {
for (y = 0; int_nums[y] != 0 ; y++) {
int l1 = snprintf(0, 0, int_fmt[x], int_nums[y]);
int l2 = snprintf(buf1, sizeof(buf1), int_fmt[x], int_nums[y]);
sprintf (buf2, int_fmt[x], int_nums[y]);
if (strcmp (buf1, buf2)) {
printf("snprintf doesn't match Format: %s\n\tsnprintf = [%s]\n\t sprintf = [%s]\n",
int_fmt[x], buf1, buf2);
fail++;
}
if (l1 != l2) {
printf("snprintf l1 != l2 (%d %d) %s\n", l1, l2, int_fmt[x]);
fail++;
}
num++;
}
}
for (x = 0; str_fmt[x] ; x++) {
for (y = 0; str_vals[y] != 0 ; y++) {
int l1 = snprintf(nullptr, 0, str_fmt[x], str_vals[y]);
int l2 = snprintf(buf1, sizeof(buf1), str_fmt[x], str_vals[y]);
sprintf (buf2, str_fmt[x], str_vals[y]);
if (strcmp (buf1, buf2)) {
printf("snprintf doesn't match Format: %s\n\tsnprintf = [%s]\n\t sprintf = [%s]\n",
str_fmt[x], buf1, buf2);
fail++;
}
if (l1 != l2) {
printf("snprintf l1 != l2 (%d %d) %s\n", l1, l2, str_fmt[x]);
fail++;
}
num++;
}
}
printf ("%d tests failed out of %d.\n", fail, num);
printf("seeing how many digits we support\n");
{
double v0 = 0.12345678901234567890123456789012345678901;
for (x=0; x<100; x++) {
snprintf(buf1, sizeof(buf1), "%1.1f", v0*pow(10, x));
sprintf(buf2, "%1.1f", v0*pow(10, x));
if (strcmp(buf1, buf2) != 0) {
printf("we seem to support %d digits\n", x-1);
break;
}
}
}
return 0;
}
#endif /* SNPRINTF_TEST */
/* vim:set ts=4 sw=4 et: */

View File

@ -566,11 +566,6 @@ void UiPacker::uiTestTotal() { uiFooter("Tested"); }
**************************************************************************/
bool UiPacker::uiFileInfoStart() {
#if defined(_WIN32) // msvcrt
#define PRLLD "I64d"
#else
#define PRLLD "lld"
#endif
total_files++;
int fg = con_fg(stdout, FG_CYAN);
@ -578,16 +573,15 @@ bool UiPacker::uiFileInfoStart() {
fg = con_fg(stdout, fg);
UNUSED(fg);
if (p->ph.c_len > 0) {
con_fprintf(stdout, " %8" PRLLD " bytes", (long long) p->file_size);
con_fprintf(stdout, " %8llu bytes", p->file_size_u);
con_fprintf(stdout, ", compressed by UPX %d, method %d, level %d, filter 0x%02x/0x%02x\n",
p->ph.version, p->ph.method, p->ph.level, p->ph.filter, p->ph.filter_cto);
return false;
} else {
con_fprintf(stdout, " %8" PRLLD " bytes", (long long) p->file_size);
con_fprintf(stdout, " %8llu bytes", p->file_size_u);
con_fprintf(stdout, ", not compressed by UPX\n");
return true;
}
#undef PRLLD
}
void UiPacker::uiFileInfoEnd() { uiUpdate(); }
@ -628,8 +622,8 @@ void UiPacker::uiFooter(const char *t) {
}
}
void UiPacker::uiUpdate(off_t fc_len, off_t fu_len) {
update_fc_len = (fc_len >= 0) ? fc_len : p->file_size;
void UiPacker::uiUpdate(upx_off_t fc_len, upx_off_t fu_len) {
update_fc_len = (fc_len >= 0) ? fc_len : p->file_size_u;
update_fu_len = (fu_len >= 0) ? fu_len : p->ph.u_file_size;
update_c_len = p->ph.c_len;
update_u_len = p->ph.u_len;

View File

@ -76,7 +76,7 @@ protected:
virtual void doCallback(unsigned isize, unsigned osize);
protected:
virtual void uiUpdate(off_t fc_len = -1, off_t fu_len = -1);
virtual void uiUpdate(upx_off_t fc_len = -1, upx_off_t fu_len = -1);
public:
static void uiHeader();