diff options
author | Nick Mathewson <nickm@torproject.org> | 2013-07-19 13:03:23 -0400 |
---|---|---|
committer | Nick Mathewson <nickm@torproject.org> | 2013-07-19 13:26:25 -0400 |
commit | 5343ee1a06ebb959fc77753898015186b94a5daa (patch) | |
tree | 22575131739f42d7c4435cd28f42e09763861f81 | |
parent | 8f0755fa85b9c1fb38fd122719e483cc11d89069 (diff) | |
download | tor-5343ee1a06ebb959fc77753898015186b94a5daa.tar tor-5343ee1a06ebb959fc77753898015186b94a5daa.tar.gz |
Add a signal-safe decimal formatting function
-rw-r--r-- | src/common/util.c | 33 | ||||
-rw-r--r-- | src/common/util.h | 1 | ||||
-rw-r--r-- | src/test/test_util.c | 51 |
3 files changed, 85 insertions, 0 deletions
diff --git a/src/common/util.c b/src/common/util.c index 0e8d34eaf..25ea13371 100644 --- a/src/common/util.c +++ b/src/common/util.c @@ -3441,6 +3441,39 @@ format_hex_number_sigsafe(unsigned int x, char *buf, int buf_len) return len; } +/** 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; +} + #ifndef _WIN32 /** Format <b>child_state</b> and <b>saved_errno</b> as a hex string placed in * <b>hex_errno</b>. Called between fork and _exit, so must be signal-handler diff --git a/src/common/util.h b/src/common/util.h index 0a8e4a23f..f6d828796 100644 --- a/src/common/util.h +++ b/src/common/util.h @@ -520,6 +520,7 @@ int32_t tor_weak_random_range(tor_weak_rng_t *rng, int32_t top); #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_dec_number_sigsafe(unsigned long x, char *buf, int max_len); #ifdef UTIL_PRIVATE /* Prototypes for private functions only used by util.c (and unit tests) */ diff --git a/src/test/test_util.c b/src/test/test_util.c index f7513c0f3..b331a804b 100644 --- a/src/test/test_util.c +++ b/src/test/test_util.c @@ -2671,6 +2671,56 @@ test_util_format_hex_number(void *ptr) } /** + * Test for format_hex_number_sigsafe() + */ + +static void +test_util_format_dec_number(void *ptr) +{ + int i, len; + char buf[33]; + const struct { + const char *str; + unsigned int x; + } test_data[] = { + {"0", 0}, + {"1", 1}, + {"1234", 1234}, + {"12345678", 12345678}, + {"99999999", 99999999}, + {"100000000", 100000000}, + {"4294967295", 4294967295u}, +#if UINT_MAX > 0xffffffff + {"18446744073709551615", 18446744073709551615u }, +#endif + {NULL, 0} + }; + + (void)ptr; + + for (i = 0; test_data[i].str != NULL; ++i) { + len = format_dec_number_sigsafe(test_data[i].x, buf, sizeof(buf)); + test_neq(len, 0); + test_eq(len, strlen(buf)); + test_streq(buf, test_data[i].str); + + len = format_dec_number_sigsafe(test_data[i].x, buf, + (int)(strlen(test_data[i].str) + 1)); + test_eq(len, strlen(buf)); + test_streq(buf, test_data[i].str); + } + + test_eq(4, format_dec_number_sigsafe(7331, buf, 5)); + test_streq(buf, "7331"); + test_eq(0, format_dec_number_sigsafe(7331, buf, 4)); + test_eq(1, format_dec_number_sigsafe(0, buf, 2)); + test_eq(0, format_dec_number_sigsafe(0, buf, 1)); + + done: + return; +} + +/** * Test that we can properly format a Windows command line */ static void @@ -3362,6 +3412,7 @@ struct testcase_t util_tests[] = { UTIL_TEST(spawn_background_fail, 0), UTIL_TEST(spawn_background_partial_read, 0), UTIL_TEST(format_hex_number, 0), + UTIL_TEST(format_dec_number, 0), UTIL_TEST(join_win_cmdline, 0), UTIL_TEST(split_lines, 0), UTIL_TEST(n_bits_set, 0), |