1
0
mirror of https://github.com/upx/upx synced 2025-10-05 19:20:23 +08:00

Cleanup snprintf.cpp.

This commit is contained in:
Markus F.X.J. Oberhumer 2017-01-29 14:11:46 +01:00
parent 1aa2a6b054
commit e1a8c932ee

View File

@ -111,11 +111,12 @@
#define DP_F_UP (1 << 5) #define DP_F_UP (1 << 5)
#define DP_F_UNSIGNED (1 << 6) #define DP_F_UNSIGNED (1 << 6)
/* Conversion Flags */ /* Length modifier */
#define DP_C_SHORT 1 #define DP_C_CHAR 1
#define DP_C_LONG 2 #define DP_C_SHORT 2
#define DP_C_LDOUBLE 3 #define DP_C_LONG 3
#define DP_C_LLONG 4 #define DP_C_LLONG 4
#define DP_C_LDOUBLE 5
#define char_to_int(p) ((p) - '0') #define char_to_int(p) ((p) - '0')
#undef MAX #undef MAX
@ -131,34 +132,32 @@ __acc_static_forceinline void dopr_outch(char *buffer, size_t *currsize, size_t
*currsize += 1; *currsize += 1;
} }
static void fmtstr(char *buffer, size_t *currsize, size_t maxsize, const char *value, int flags, static void fmtstr(char *buffer, size_t *currsize, size_t maxsize, const char *strvalue, int strln,
int min, int max) { int flags, int min, int max) {
int padlen, strln; /* amount to pad */ int padlen; /* amount to pad */
int cnt = 0; int cnt = 0;
#ifdef DEBUG_SNPRINTF #ifdef DEBUG_SNPRINTF
printf("fmtstr min=%d max=%d s=[%s]\n", min, max, value); printf("fmtstr min=%d max=%d s=[%s]\n", min, max, strvalue);
#endif #endif
if (value == NULL) assert(strvalue != NULL);
value = "<NULL>";
strln = (int) strlen(value);
padlen = min - strln; padlen = min - strln;
if (padlen < 0) if (padlen < 0)
padlen = 0; padlen = 0;
if (flags & DP_F_MINUS) if (flags & DP_F_MINUS)
padlen = -padlen; /* Left Justify */ padlen = -padlen; /* Left Justify */
while (padlen > 0 && cnt < max) { while (cnt < max && padlen > 0) {
dopr_outch(buffer, currsize, maxsize, ' '); dopr_outch(buffer, currsize, maxsize, ' ');
--padlen; --padlen;
++cnt; ++cnt;
} }
while (*value && cnt < max) { while (cnt < max && *strvalue) {
dopr_outch(buffer, currsize, maxsize, *value); dopr_outch(buffer, currsize, maxsize, *strvalue);
++value; ++strvalue;
++cnt; ++cnt;
} }
while (padlen < 0 && cnt < max) { while (cnt < max && padlen < 0) {
dopr_outch(buffer, currsize, maxsize, ' '); dopr_outch(buffer, currsize, maxsize, ' ');
++padlen; ++padlen;
++cnt; ++cnt;
@ -480,7 +479,6 @@ static size_t dopr(char *buffer, size_t maxsize, const char *format, va_list arg
#if !(NO_FLOAT) #if !(NO_FLOAT)
LDOUBLE fvalue; LDOUBLE fvalue;
#endif #endif
const char *strvalue;
int min; int min;
int max; int max;
int state; int state;
@ -494,6 +492,10 @@ static size_t dopr(char *buffer, size_t maxsize, const char *format, va_list arg
ch = *format++; ch = *format++;
while (state != DP_S_DONE) { while (state != DP_S_DONE) {
unsigned base;
const char *strvalue;
int strln;
if (ch == '\0') if (ch == '\0')
state = DP_S_DONE; state = DP_S_DONE;
@ -543,6 +545,8 @@ static size_t dopr(char *buffer, size_t maxsize, const char *format, va_list arg
} else { } else {
state = DP_S_DOT; state = DP_S_DOT;
} }
assert(min > 0 - UPX_RSIZE_MAX_STR);
assert(min < UPX_RSIZE_MAX_STR);
break; break;
case DP_S_DOT: case DP_S_DOT:
if (ch == '.') { if (ch == '.') {
@ -565,21 +569,39 @@ static size_t dopr(char *buffer, size_t maxsize, const char *format, va_list arg
} else { } else {
state = DP_S_MOD; state = DP_S_MOD;
} }
assert(max > 0 - UPX_RSIZE_MAX_STR);
assert(max < UPX_RSIZE_MAX_STR);
break; break;
case DP_S_MOD: case DP_S_MOD:
switch (ch) { switch (ch) {
case 'h': case 'h':
cflags = DP_C_SHORT; cflags = DP_C_SHORT;
ch = *format++; ch = *format++;
if (ch == 'h') {
cflags = DP_C_CHAR;
ch = *format++;
}
break; break;
case 'l': case 'l':
cflags = DP_C_LONG; cflags = DP_C_LONG;
ch = *format++; ch = *format++;
if (ch == 'l') { /* It's a long long */ if (ch == 'l') {
cflags = DP_C_LLONG; cflags = DP_C_LLONG;
ch = *format++; ch = *format++;
} }
break; 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': case 'L':
cflags = DP_C_LDOUBLE; cflags = DP_C_LDOUBLE;
ch = *format++; ch = *format++;
@ -593,57 +615,99 @@ static size_t dopr(char *buffer, size_t maxsize, const char *format, va_list arg
switch (ch) { switch (ch) {
case 'd': case 'd':
case 'i': case 'i':
if (cflags == DP_C_SHORT) if (cflags == DP_C_CHAR)
value = va_arg(args, int); 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) else if (cflags == DP_C_LONG)
value = va_arg(args, long int); value = (LLONG) va_arg(args, long);
else if (cflags == DP_C_LLONG) else if (cflags == DP_C_LLONG)
value = va_arg(args, LLONG); value = (LLONG) va_arg(args, LLONG);
else else
value = va_arg(args, int); value = (LLONG) va_arg(args, int);
fmtint(buffer, &currsize, maxsize, value, 10, min, max, flags);
break;
case 'o':
flags |= DP_F_UNSIGNED;
if (cflags == DP_C_SHORT)
value = va_arg(args, unsigned int);
else if (cflags == DP_C_LONG)
value = (long) va_arg(args, unsigned long int);
else if (cflags == DP_C_LLONG)
value = (LLONG) va_arg(args, ULLONG);
else
value = (long) va_arg(args, unsigned int);
fmtint(buffer, &currsize, maxsize, value, 8, min, max, flags);
break;
case 'u':
flags |= DP_F_UNSIGNED;
if (cflags == DP_C_SHORT)
value = va_arg(args, unsigned int);
else if (cflags == DP_C_LONG)
value = (long) va_arg(args, unsigned long int);
else if (cflags == DP_C_LLONG)
value = (LLONG) va_arg(args, ULLONG);
else
value = (long) va_arg(args, unsigned int);
fmtint(buffer, &currsize, maxsize, value, 10, min, max, flags); fmtint(buffer, &currsize, maxsize, value, 10, min, max, flags);
break; break;
case 'X': case 'X':
flags |= DP_F_UP; flags |= DP_F_UP;
/*fallthrough*/
case 'x': case 'x':
base = 16;
l_fmtuint:
flags |= DP_F_UNSIGNED; flags |= DP_F_UNSIGNED;
if (cflags == DP_C_SHORT) if (cflags == DP_C_CHAR)
value = va_arg(args, unsigned int); 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) else if (cflags == DP_C_LONG)
value = (long) va_arg(args, unsigned long int); value = (ULLONG) va_arg(args, unsigned long);
else if (cflags == DP_C_LLONG) else if (cflags == DP_C_LLONG)
value = (LLONG) va_arg(args, ULLONG); value = (ULLONG) va_arg(args, ULLONG);
else else
value = (long) va_arg(args, unsigned int); value = (ULLONG) va_arg(args, unsigned);
fmtint(buffer, &currsize, maxsize, value, 16, min, max, flags); 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 != NULL);
*num = (signed char) currsize;
} else if (cflags == DP_C_SHORT) {
short *num;
num = va_arg(args, short *);
assert(num != NULL);
*num = (short) currsize;
} else if (cflags == DP_C_LONG) {
long *num;
num = va_arg(args, long *);
assert(num != NULL);
*num = (long) currsize;
} else if (cflags == DP_C_LLONG) {
LLONG *num;
num = va_arg(args, LLONG *);
assert(num != NULL);
*num = (LLONG) currsize;
} else {
int *num;
num = va_arg(args, int *);
assert(num != NULL);
*num = (int) currsize;
}
break;
case '%':
dopr_outch(buffer, &currsize, maxsize, ch);
break; break;
#if !(NO_FLOAT) #if !(NO_FLOAT)
case 'F': case 'F':
flags |= DP_F_UP; flags |= DP_F_UP;
/*fallthrough*/
case 'f': case 'f':
if (cflags == DP_C_LDOUBLE) if (cflags == DP_C_LDOUBLE)
fvalue = va_arg(args, LDOUBLE); fvalue = va_arg(args, LDOUBLE);
@ -654,6 +718,7 @@ static size_t dopr(char *buffer, size_t maxsize, const char *format, va_list arg
break; break;
case 'E': case 'E':
flags |= DP_F_UP; flags |= DP_F_UP;
/*fallthrough*/
case 'e': case 'e':
if (cflags == DP_C_LDOUBLE) if (cflags == DP_C_LDOUBLE)
fvalue = va_arg(args, LDOUBLE); fvalue = va_arg(args, LDOUBLE);
@ -662,6 +727,7 @@ static size_t dopr(char *buffer, size_t maxsize, const char *format, va_list arg
break; break;
case 'G': case 'G':
flags |= DP_F_UP; flags |= DP_F_UP;
/*fallthrough*/
case 'g': case 'g':
if (cflags == DP_C_LDOUBLE) if (cflags == DP_C_LDOUBLE)
fvalue = va_arg(args, LDOUBLE); fvalue = va_arg(args, LDOUBLE);
@ -680,46 +746,6 @@ static size_t dopr(char *buffer, size_t maxsize, const char *format, va_list arg
assert(0); assert(0);
exit(255); exit(255);
#endif /* !(NO_FLOAT) */ #endif /* !(NO_FLOAT) */
case 'c':
dopr_outch(buffer, &currsize, maxsize, va_arg(args, int));
break;
case 's':
strvalue = va_arg(args, const char *);
if (!strvalue)
strvalue = "(NULL)";
if (max == -1)
max = (int) strlen(strvalue);
if (min > 0 && max >= 0 && min > max)
max = min;
fmtstr(buffer, &currsize, maxsize, strvalue, 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_SHORT) {
short int *num;
num = va_arg(args, short int *);
*num = (short int) currsize;
} else if (cflags == DP_C_LONG) {
long int *num;
num = va_arg(args, long int *);
*num = (long int) currsize;
} else if (cflags == DP_C_LLONG) {
LLONG *num;
num = va_arg(args, LLONG *);
*num = (LLONG) currsize;
} else {
int *num;
num = va_arg(args, int *);
*num = (int) currsize;
}
break;
case '%':
dopr_outch(buffer, &currsize, maxsize, ch);
break;
default: default:
/* Unknown, skip */ /* Unknown, skip */
break; break;
@ -783,7 +809,14 @@ int upx_vasprintf(char **ptr, const char *format, va_list ap) {
assert(ptr != NULL); assert(ptr != NULL);
*ptr = NULL; *ptr = NULL;
#if defined(va_copy)
va_list ap_copy;
va_copy(ap_copy, ap);
len = upx_vsnprintf(NULL, 0, format, ap_copy);
va_end(ap_copy);
#else
len = upx_vsnprintf(NULL, 0, format, ap); len = upx_vsnprintf(NULL, 0, format, ap);
#endif
if (len >= 0) { if (len >= 0) {
*ptr = (char *) malloc(len + 1); *ptr = (char *) malloc(len + 1);
assert(*ptr != NULL); assert(*ptr != NULL);