diff options
author | Nick Mathewson <nickm@torproject.org> | 2013-10-18 10:37:23 -0700 |
---|---|---|
committer | Nick Mathewson <nickm@torproject.org> | 2013-11-18 10:43:16 -0500 |
commit | c2dfae78d3a881af7cfe2fb4a79da7e3598788fc (patch) | |
tree | 3971d2f4e08416c8cbcfeb43467b63215b7814c9 /src/common/util.c | |
parent | c3ea946839704c4f1f0369a1e91bdb749991e346 (diff) | |
download | tor-c2dfae78d3a881af7cfe2fb4a79da7e3598788fc.tar.gz tor-c2dfae78d3a881af7cfe2fb4a79da7e3598788fc.zip |
Refactor format_*_number_sigsafe to have a common implementation
Diffstat (limited to 'src/common/util.c')
-rw-r--r-- | src/common/util.c | 113 |
1 files changed, 48 insertions, 65 deletions
diff --git a/src/common/util.c b/src/common/util.c index bbb604492d..cb23e7e9ae 100644 --- a/src/common/util.c +++ b/src/common/util.c @@ -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 |