Refactor format_*_number_sigsafe to have a common implementation

This commit is contained in:
Nick Mathewson 2013-10-18 10:37:23 -07:00
parent c3ea946839
commit c2dfae78d3
2 changed files with 49 additions and 66 deletions

View File

@ -3396,6 +3396,51 @@ tor_join_win_cmdline(const char *argv[])
return joined_argv;
}
/* As format_{hex,dex}_number_sigsafe, but takes a <b>radix</b> argument
* in range 2..16 inclusive. */
static int
format_number_sigsafe(unsigned long x, char *buf, int buf_len,
unsigned int radix)
{
unsigned long tmp;
int len;
char *cp;
/* NOT tor_assert. This needs to be safe to run from within a signal handler,
* and from within the 'tor_assert() has failed' code. */
if (radix < 2 || radix > 16)
return 0;
/* Count how many digits we need. */
tmp = x;
len = 1;
while (tmp >= radix) {
tmp /= radix;
++len;
}
/* Not long enough */
if (!buf || len >= buf_len)
return 0;
cp = buf + len;
*cp = '\0';
do {
unsigned digit = x % radix;
tor_assert(cp > buf);
--cp;
*cp = "0123456789ABCDEF"[digit];
x /= radix;
} while (x);
/* NOT tor_assert; see above. */
if (cp != buf) {
abort();
}
return len;
}
/**
* Helper function to output hex numbers from within a signal handler.
*
@ -3418,78 +3463,16 @@ tor_join_win_cmdline(const char *argv[])
* arbitrary C functions.
*/
int
format_hex_number_sigsafe(unsigned int x, char *buf, int buf_len)
format_hex_number_sigsafe(unsigned long x, char *buf, int buf_len)
{
int len;
unsigned int tmp;
char *cur;
/* Sanity check */
if (!buf || buf_len <= 1)
return 0;
/* How many chars do we need for x? */
if (x > 0) {
len = 0;
tmp = x;
while (tmp > 0) {
tmp >>= 4;
++len;
}
} else {
len = 1;
}
/* Bail if we would go past the end of the buffer */
if (len+1 > buf_len)
return 0;
/* Point to last one */
cur = buf + len - 1;
/* Convert x to hex */
do {
*cur-- = "0123456789ABCDEF"[x & 0xf];
x >>= 4;
} while (x != 0 && cur >= buf);
buf[len] = '\0';
/* Return len */
return len;
return format_number_sigsafe(x, buf, buf_len, 16);
}
/** As format_hex_number_sigsafe, but format the number in base 10. */
int
format_dec_number_sigsafe(unsigned long x, char *buf, int buf_len)
{
int len;
unsigned long tmp;
char *cp;
tmp = x;
len = 1;
while (tmp > 9) {
tmp /= 10;
++len;
}
if (len >= buf_len)
return 0;
cp = buf + len;
*cp = '\0';
do {
unsigned digit = x % 10;
tor_assert(cp > buf);
--cp;
*cp = '0' + digit;
x /= 10;
} while (x);
tor_assert(cp == buf);
return len;
return format_number_sigsafe(x, buf, buf_len, 10);
}
#ifndef _WIN32

View File

@ -519,7 +519,7 @@ int32_t tor_weak_random_range(tor_weak_rng_t *rng, int32_t top);
* <b>n</b> */
#define tor_weak_random_one_in_n(rng, n) (0==tor_weak_random_range((rng),(n)))
int format_hex_number_sigsafe(unsigned int x, char *buf, int max_len);
int format_hex_number_sigsafe(unsigned long x, char *buf, int max_len);
int format_dec_number_sigsafe(unsigned long x, char *buf, int max_len);
#ifdef UTIL_PRIVATE