aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNick Mathewson <nickm@torproject.org>2013-07-19 13:03:23 -0400
committerNick Mathewson <nickm@torproject.org>2013-07-19 13:26:25 -0400
commit5343ee1a06ebb959fc77753898015186b94a5daa (patch)
tree22575131739f42d7c4435cd28f42e09763861f81
parent8f0755fa85b9c1fb38fd122719e483cc11d89069 (diff)
downloadtor-5343ee1a06ebb959fc77753898015186b94a5daa.tar
tor-5343ee1a06ebb959fc77753898015186b94a5daa.tar.gz
Add a signal-safe decimal formatting function
-rw-r--r--src/common/util.c33
-rw-r--r--src/common/util.h1
-rw-r--r--src/test/test_util.c51
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),