[tor-commits] [tor/master] Avoid overflow in format_time_interval, create unit tests

nickm at torproject.org nickm at torproject.org
Mon Oct 13 17:20:11 UTC 2014


commit f51418aabcc2af47f61a97f818b013ade6e45208
Author: teor <teor2345 at gmail.com>
Date:   Sun Oct 12 20:50:10 2014 +1100

    Avoid overflow in format_time_interval, create unit tests
    
    Fix an instance of integer overflow in format_time_interval() when
    taking the absolute value of the supplied signed interval value.
    Fixes bug 13393.
    
    Create unit tests for format_time_interval().
---
 .../bug13393-format-time-interval-overflow-test    |    6 +
 src/common/util.c                                  |    6 +-
 src/test/test_util.c                               |  423 ++++++++++++++++++++
 3 files changed, 434 insertions(+), 1 deletion(-)

diff --git a/changes/bug13393-format-time-interval-overflow-test b/changes/bug13393-format-time-interval-overflow-test
new file mode 100644
index 0000000..cc15572
--- /dev/null
+++ b/changes/bug13393-format-time-interval-overflow-test
@@ -0,0 +1,6 @@
+  o Minor bugfixes:
+    - Fix an instance of integer overflow in format_time_interval().
+      Fixes bug 13393.
+
+  o Minor features (test):
+    - Create unit tests for format_time_interval(). With bug 13393.
diff --git a/src/common/util.c b/src/common/util.c
index f4d293c..0ea7095 100644
--- a/src/common/util.c
+++ b/src/common/util.c
@@ -1670,7 +1670,11 @@ format_time_interval(char *out, size_t out_len, long interval)
 {
   /* We only report seconds if there's no hours. */
   long sec = 0, min = 0, hour = 0, day = 0;
-  if (interval < 0)
+  
+  /* -LONG_MIN is LONG_MAX + 1, which causes signed overflow */
+  if (interval < -LONG_MAX)
+    interval = LONG_MAX;
+  else if (interval < 0)
     interval = -interval;
 
   if (interval >= 86400) {
diff --git a/src/test/test_util.c b/src/test/test_util.c
index c67aa71..3fed1f7 100644
--- a/src/test/test_util.c
+++ b/src/test/test_util.c
@@ -22,6 +22,7 @@
 #include <tchar.h>
 #endif
 #include <math.h>
+#include <ctype.h>
 
 /* XXXX this is a minimal wrapper to make the unit tests compile with the
  * changed tor_timegm interface. */
@@ -2068,6 +2069,427 @@ test_util_sscanf(void *arg)
   ;
 }
 
+#define tt_char_op(a,op,b) tt_assert_op_type(a,op,b,char,"%c")
+#define tt_ci_char_op(a,op,b) tt_char_op(tolower(a),op,tolower(b))
+
+static void
+test_util_format_time_interval(void *arg)
+{
+  /* use the same sized buffer and integers as tor uses */
+#define DBUF_SIZE 64
+  char dbuf[DBUF_SIZE];
+#define T_        "%ld"
+  long sec, min, hour, day;
+  
+  /* we don't care about the exact spelling of the
+   * second(s), minute(s), hour(s), day(s) labels */
+#define LABEL_SIZE 21
+#define L_        "%20s"
+  char label_s[LABEL_SIZE];
+  char label_m[LABEL_SIZE];
+  char label_h[LABEL_SIZE];
+  char label_d[LABEL_SIZE];
+
+#define TL_       T_ " " L_
+  
+  int r;
+  
+  (void)arg;
+  
+  /* In these tests, we're not picky about
+   * spelling or abbreviations */
+  
+  /* seconds: 0, 1, 9, 10, 59 */
+  
+  /* ignore exact spelling of "second(s)"*/
+  format_time_interval(dbuf, sizeof(dbuf), 0);
+  tt_int_op(strnlen(dbuf, DBUF_SIZE),<=, DBUF_SIZE - 1);
+  r = tor_sscanf(dbuf, TL_, &sec, label_s);
+  tt_int_op(r,==, 2);
+  tt_ci_char_op(label_s[0],==, 's');
+  tt_int_op(sec,==, 0);
+  
+  format_time_interval(dbuf, sizeof(dbuf), 1);
+  tt_int_op(strnlen(dbuf, DBUF_SIZE),<=, DBUF_SIZE - 1);
+  r = tor_sscanf(dbuf, TL_, &sec, label_s);
+  tt_int_op(r,==, 2);
+  tt_ci_char_op(label_s[0],==, 's');
+  tt_int_op(sec,==, 1);
+  
+  format_time_interval(dbuf, sizeof(dbuf), 10);
+  tt_int_op(strnlen(dbuf, DBUF_SIZE),<=, DBUF_SIZE - 1);
+  r = tor_sscanf(dbuf, TL_, &sec, label_s);
+  tt_int_op(r,==, 2);
+  tt_ci_char_op(label_s[0],==, 's');
+  tt_int_op(sec,==, 10);
+  
+  format_time_interval(dbuf, sizeof(dbuf), 59);
+  tt_int_op(strnlen(dbuf, DBUF_SIZE),<=, DBUF_SIZE - 1);
+  r = tor_sscanf(dbuf, TL_, &sec, label_s);
+  tt_int_op(r,==, 2);
+  tt_ci_char_op(label_s[0],==, 's');
+  tt_int_op(sec,==, 59);
+  
+  /* negative seconds are reported as their absolute value */
+  
+  format_time_interval(dbuf, sizeof(dbuf), -4);
+  tt_int_op(strnlen(dbuf, DBUF_SIZE),<=, DBUF_SIZE - 1);
+  r = tor_sscanf(dbuf, TL_, &sec, label_s);
+  tt_int_op(r,==, 2);
+  tt_ci_char_op(label_s[0],==, 's');
+  tt_int_op(sec,==, 4);
+  tt_int_op(strnlen(dbuf, DBUF_SIZE),<=, DBUF_SIZE - 1);
+  
+  format_time_interval(dbuf, sizeof(dbuf), -32);
+  tt_int_op(strnlen(dbuf, DBUF_SIZE),<=, DBUF_SIZE - 1);
+  r = tor_sscanf(dbuf, TL_, &sec, label_s);
+  tt_int_op(r,==, 2);
+  tt_ci_char_op(label_s[0],==, 's');
+  tt_int_op(sec,==, 32);
+  tt_int_op(strnlen(dbuf, DBUF_SIZE),<=, DBUF_SIZE - 1);
+  
+  /* minutes: 1:00, 1:01, 1:59, 2:00, 2:01, 59:59 */
+  
+  /* ignore trailing "0 second(s)", if present */
+  format_time_interval(dbuf, sizeof(dbuf), 60);
+  tt_int_op(strnlen(dbuf, DBUF_SIZE),<=, DBUF_SIZE - 1);
+  r = tor_sscanf(dbuf, TL_, &min, label_m);
+  tt_int_op(r,==, 2);
+  tt_ci_char_op(label_m[0],==, 'm');
+  tt_int_op(min,==, 1);
+  tt_int_op(strnlen(dbuf, DBUF_SIZE),<=, DBUF_SIZE - 1);
+
+  /* ignore exact spelling of "minute(s)," and "second(s)" */
+  format_time_interval(dbuf, sizeof(dbuf), 60 + 1);
+  tt_int_op(strnlen(dbuf, DBUF_SIZE),<=, DBUF_SIZE - 1);
+  r = tor_sscanf(dbuf, TL_ " " TL_,
+                 &min, label_m, &sec, label_s);
+  tt_int_op(r,==, 4);
+  tt_int_op(min,==, 1);
+  tt_ci_char_op(label_m[0],==, 'm');
+  tt_int_op(sec,==, 1);
+  tt_ci_char_op(label_s[0],==, 's');
+  tt_int_op(strnlen(dbuf, DBUF_SIZE),<=, DBUF_SIZE - 1);
+  
+  format_time_interval(dbuf, sizeof(dbuf), 60*2 - 1);
+  tt_int_op(strnlen(dbuf, DBUF_SIZE),<=, DBUF_SIZE - 1);
+  r = tor_sscanf(dbuf, TL_ " " TL_,
+                 &min, label_m, &sec, label_s);
+  tt_int_op(r,==, 4);
+  tt_int_op(min,==, 1);
+  tt_ci_char_op(label_m[0],==, 'm');
+  tt_int_op(sec,==, 59);
+  tt_ci_char_op(label_s[0],==, 's');
+  
+  /* ignore trailing "0 second(s)", if present */
+  format_time_interval(dbuf, sizeof(dbuf), 60*2);
+  tt_int_op(strnlen(dbuf, DBUF_SIZE),<=, DBUF_SIZE - 1);
+  r = tor_sscanf(dbuf, TL_, &min, label_m);
+  tt_int_op(r,==, 2);
+  tt_int_op(min,==, 2);
+  tt_ci_char_op(label_m[0],==, 'm');
+  
+  /* ignore exact spelling of "minute(s)," and "second(s)" */
+  format_time_interval(dbuf, sizeof(dbuf), 60*2 + 1);
+  tt_int_op(strnlen(dbuf, DBUF_SIZE),<=, DBUF_SIZE - 1);
+  r = tor_sscanf(dbuf, TL_ " " TL_,
+                 &min, label_m, &sec, label_s);
+  tt_int_op(r,==, 4);
+  tt_int_op(min,==, 2);
+  tt_ci_char_op(label_m[0],==, 'm');
+  tt_int_op(sec,==, 1);
+  tt_ci_char_op(label_s[0],==, 's');
+  
+  format_time_interval(dbuf, sizeof(dbuf), 60*60 - 1);
+  tt_int_op(strnlen(dbuf, DBUF_SIZE),<=, DBUF_SIZE - 1);
+  r = tor_sscanf(dbuf, TL_ " " TL_,
+                 &min, label_m, &sec, label_s);
+  tt_int_op(r,==, 4);
+  tt_int_op(min,==, 59);
+  tt_ci_char_op(label_m[0],==, 'm');
+  tt_int_op(sec,==, 59);
+  tt_ci_char_op(label_s[0],==, 's');
+  
+  /* negative minutes are reported as their absolute value */
+  
+  /* ignore trailing "0 second(s)", if present */
+  format_time_interval(dbuf, sizeof(dbuf), -3*60);
+  tt_int_op(strnlen(dbuf, DBUF_SIZE),<=, DBUF_SIZE - 1);
+  r = tor_sscanf(dbuf, TL_, &min, label_m);
+  tt_int_op(r,==, 2);
+  tt_int_op(min,==, 3);
+  tt_ci_char_op(label_m[0],==, 'm');
+  
+  /* ignore exact spelling of "minute(s)," and "second(s)" */
+  format_time_interval(dbuf, sizeof(dbuf), -96);
+  tt_int_op(strnlen(dbuf, DBUF_SIZE),<=, DBUF_SIZE - 1);
+  r = tor_sscanf(dbuf, TL_ " " TL_,
+                 &min, label_m, &sec, label_s);
+  tt_int_op(r,==, 4);
+  tt_int_op(min,==, 1);
+  tt_ci_char_op(label_m[0],==, 'm');
+  tt_int_op(sec,==, 36);
+  tt_ci_char_op(label_s[0],==, 's');
+  
+  format_time_interval(dbuf, sizeof(dbuf), -2815);
+  tt_int_op(strnlen(dbuf, DBUF_SIZE),<=, DBUF_SIZE - 1);
+  r = tor_sscanf(dbuf, TL_ " " TL_,
+                 &min, label_m, &sec, label_s);
+  tt_int_op(r,==, 4);
+  tt_int_op(min,==, 46);
+  tt_ci_char_op(label_m[0],==, 'm');
+  tt_int_op(sec,==, 55);
+  tt_ci_char_op(label_s[0],==, 's');
+  
+  /* hours: 1:00, 1:00:01, 1:01, 23:59, 23:59:59 */
+  /* always ignore trailing seconds, if present */
+  
+  /* ignore trailing "0 minute(s)" etc., if present */
+  format_time_interval(dbuf, sizeof(dbuf), 60*60);
+  tt_int_op(strnlen(dbuf, DBUF_SIZE),<=, DBUF_SIZE - 1);
+  r = tor_sscanf(dbuf, TL_, &hour, label_h);
+  tt_int_op(r,==, 2);
+  tt_int_op(hour,==, 1);
+  tt_ci_char_op(label_h[0],==, 'h');
+  
+  format_time_interval(dbuf, sizeof(dbuf), 60*60 + 1);
+  tt_int_op(strnlen(dbuf, DBUF_SIZE),<=, DBUF_SIZE - 1);
+  r = tor_sscanf(dbuf, TL_, &hour, label_h);
+  tt_int_op(r,==, 2);
+  tt_int_op(hour,==, 1);
+  tt_ci_char_op(label_h[0],==, 'h');
+  
+  /* ignore exact spelling of "hour(s)," etc. */
+  format_time_interval(dbuf, sizeof(dbuf), 60*60 + 60);
+  tt_int_op(strnlen(dbuf, DBUF_SIZE),<=, DBUF_SIZE - 1);
+  r = tor_sscanf(dbuf, TL_ " " TL_,
+                 &hour, label_h, &min, label_m);
+  tt_int_op(r,==, 4);
+  tt_int_op(hour,==, 1);
+  tt_ci_char_op(label_h[0],==, 'h');
+  tt_int_op(min,==, 1);
+  tt_ci_char_op(label_m[0],==, 'm');
+  
+  format_time_interval(dbuf, sizeof(dbuf), 24*60*60 - 60);
+  tt_int_op(strnlen(dbuf, DBUF_SIZE),<=, DBUF_SIZE - 1);
+  r = tor_sscanf(dbuf, TL_ " " TL_,
+                 &hour, label_h, &min, label_m);
+  tt_int_op(r,==, 4);
+  tt_int_op(hour,==, 23);
+  tt_ci_char_op(label_h[0],==, 'h');
+  tt_int_op(min,==, 59);
+  tt_ci_char_op(label_m[0],==, 'm');
+  
+  format_time_interval(dbuf, sizeof(dbuf), 24*60*60 - 1);
+  tt_int_op(strnlen(dbuf, DBUF_SIZE),<=, DBUF_SIZE - 1);
+  r = tor_sscanf(dbuf, TL_ " " TL_,
+                 &hour, label_h, &min, label_m);
+  tt_int_op(r,==, 4);
+  tt_int_op(hour,==, 23);
+  tt_ci_char_op(label_h[0],==, 'h');
+  tt_int_op(min,==, 59);
+  tt_ci_char_op(label_m[0],==, 'm');
+  
+  /* negative hours are reported as their absolute value */
+  
+  /* ignore exact spelling of "hour(s)," etc., if present */
+  format_time_interval(dbuf, sizeof(dbuf), -2*60*60);
+  tt_int_op(strnlen(dbuf, DBUF_SIZE),<=, DBUF_SIZE - 1);
+  r = tor_sscanf(dbuf, TL_, &hour, label_h);
+  tt_int_op(r,==, 2);
+  tt_int_op(hour,==, 2);
+  tt_ci_char_op(label_h[0],==, 'h');
+  
+  format_time_interval(dbuf, sizeof(dbuf), -75804);
+  tt_int_op(strnlen(dbuf, DBUF_SIZE),<=, DBUF_SIZE - 1);
+  r = tor_sscanf(dbuf, TL_ " " TL_,
+                 &hour, label_h, &min, label_m);
+  tt_int_op(r,==, 4);
+  tt_int_op(hour,==, 21);
+  tt_ci_char_op(label_h[0],==, 'h');
+  tt_int_op(min,==, 3);
+  tt_ci_char_op(label_m[0],==, 'm');
+  
+  /* days: 1:00, 1:00:00:01, 1:00:01, 1:01 */
+  /* always ignore trailing seconds, if present */
+  
+  /* ignore trailing "0 hours(s)" etc., if present */
+  format_time_interval(dbuf, sizeof(dbuf), 24*60*60);
+  tt_int_op(strnlen(dbuf, DBUF_SIZE),<=, DBUF_SIZE - 1);
+  r = tor_sscanf(dbuf, TL_, &day, label_d);
+  tt_int_op(r,==, 2);
+  tt_int_op(day,==, 1);
+  tt_ci_char_op(label_d[0],==, 'd');
+  
+  format_time_interval(dbuf, sizeof(dbuf), 24*60*60 + 1);
+  tt_int_op(strnlen(dbuf, DBUF_SIZE),<=, DBUF_SIZE - 1);
+  r = tor_sscanf(dbuf, TL_, &day, label_d);
+  tt_int_op(r,==, 2);
+  tt_int_op(day,==, 1);
+  tt_ci_char_op(label_d[0],==, 'd');
+  
+  /* ignore exact spelling of "days(s)," etc. */
+  format_time_interval(dbuf, sizeof(dbuf), 24*60*60 + 60);
+  tt_int_op(strnlen(dbuf, DBUF_SIZE),<=, DBUF_SIZE - 1);
+  r = tor_sscanf(dbuf, TL_ " " TL_ " " TL_,
+                 &day, label_d, &hour, label_h, &min, label_m);
+  if (r == -1) {
+    /* ignore 0 hours(s), if present */
+    r = tor_sscanf(dbuf, TL_ " " TL_,
+                   &day, label_d, &min, label_m);
+  }
+  tt_assert(r == 4 || r == 6);
+  tt_int_op(day,==, 1);
+  tt_ci_char_op(label_d[0],==, 'd');
+  if (r == 6) {
+    tt_int_op(hour,==, 0);
+    tt_ci_char_op(label_h[0],==, 'h');
+  }
+  tt_int_op(min,==, 1);
+  tt_ci_char_op(label_m[0],==, 'm');
+  
+  /* ignore trailing "0 minutes(s)" etc., if present */
+  format_time_interval(dbuf, sizeof(dbuf), 24*60*60 + 60*60);
+  tt_int_op(strnlen(dbuf, DBUF_SIZE),<=, DBUF_SIZE - 1);
+  r = tor_sscanf(dbuf, TL_ " " TL_,
+                 &day, label_d, &hour, label_h);
+  tt_int_op(r,==, 4);
+  tt_int_op(day,==, 1);
+  tt_ci_char_op(label_d[0],==, 'd');
+  tt_int_op(hour,==, 1);
+  tt_ci_char_op(label_h[0],==, 'h');
+  
+  /* negative days are reported as their absolute value */
+  
+  format_time_interval(dbuf, sizeof(dbuf), -21936184);
+  tt_int_op(strnlen(dbuf, DBUF_SIZE),<=, DBUF_SIZE - 1);
+  r = tor_sscanf(dbuf, TL_ " " TL_ " " TL_,
+                 &day, label_d, &hour, label_h, &min, label_m);
+  tt_int_op(r,==, 6);
+  tt_int_op(day,==, 253);
+  tt_ci_char_op(label_d[0],==, 'd');
+  tt_int_op(hour,==, 21);
+  tt_ci_char_op(label_h[0],==, 'h');
+  tt_int_op(min,==, 23);
+  tt_ci_char_op(label_m[0],==, 'm');
+  
+  /* periods > 1 year are reported in days (warn?) */
+  
+  /* ignore exact spelling of "days(s)," etc., if present */
+  format_time_interval(dbuf, sizeof(dbuf), 758635154);
+  tt_int_op(strnlen(dbuf, DBUF_SIZE),<=, DBUF_SIZE - 1);
+  r = tor_sscanf(dbuf, TL_ " " TL_ " " TL_,
+                 &day, label_d, &hour, label_h, &min, label_m);
+  tt_int_op(r,==, 6);
+  tt_int_op(day,==, 8780);
+  tt_ci_char_op(label_d[0],==, 'd');
+  tt_int_op(hour,==, 11);
+  tt_ci_char_op(label_h[0],==, 'h');
+  tt_int_op(min,==, 59);
+  tt_ci_char_op(label_m[0],==, 'm');
+  
+  /* negative periods > 1 year are reported in days (warn?) */
+  
+  format_time_interval(dbuf, sizeof(dbuf), -1427014922);
+  tt_int_op(strnlen(dbuf, DBUF_SIZE),<=, DBUF_SIZE - 1);
+  r = tor_sscanf(dbuf, TL_ " " TL_ " " TL_,
+                 &day, label_d, &hour, label_h, &min, label_m);
+  tt_int_op(r,==, 6);
+  tt_int_op(day,==, 16516);
+  tt_ci_char_op(label_d[0],==, 'd');
+  tt_int_op(hour,==, 9);
+  tt_ci_char_op(label_h[0],==, 'h');
+  tt_int_op(min,==, 2);
+  tt_ci_char_op(label_m[0],==, 'm');
+  
+#if SIZEOF_LONG == 4 || SIZEOF_LONG == 8
+
+  /* We can try INT32_MIN/MAX */
+  /* Always ignore second(s) */
+  
+  /* INT32_MAX */
+  format_time_interval(dbuf, sizeof(dbuf), 2147483647);
+  tt_int_op(strnlen(dbuf, DBUF_SIZE),<=, DBUF_SIZE - 1);
+  r = tor_sscanf(dbuf, TL_ " " TL_ " " TL_,
+                 &day, label_d, &hour, label_h, &min, label_m);
+  tt_int_op(r,==, 6);
+  tt_int_op(day,==, 24855);
+  tt_ci_char_op(label_d[0],==, 'd');
+  tt_int_op(hour,==, 3);
+  tt_ci_char_op(label_h[0],==, 'h');
+  tt_int_op(min,==, 14);
+  tt_ci_char_op(label_m[0],==, 'm');
+  /* and 7 seconds - ignored */
+  
+  /* INT32_MIN: check that we get the absolute value of interval,
+   * which doesn't actually fit in int32_t.
+   * We expect INT32_MAX or INT32_MAX + 1 with 64 bit longs */
+  format_time_interval(dbuf, sizeof(dbuf), -2147483647L - 1L);
+  tt_int_op(strnlen(dbuf, DBUF_SIZE),<=, DBUF_SIZE - 1);
+  r = tor_sscanf(dbuf, TL_ " " TL_ " " TL_,
+                 &day, label_d, &hour, label_h, &min, label_m);
+  tt_int_op(r,==, 6);
+  tt_int_op(day,==, 24855);
+  tt_ci_char_op(label_d[0],==, 'd');
+  tt_int_op(hour,==, 3);
+  tt_ci_char_op(label_h[0],==, 'h');
+  tt_int_op(min,==, 14);
+  tt_ci_char_op(label_m[0],==, 'm');
+  /* and 7 or 8 seconds - ignored */
+
+#endif
+
+#if SIZEOF_LONG == 8
+
+  /* We can try INT64_MIN/MAX */
+  /* Always ignore second(s) */
+  
+  /* INT64_MAX */
+  format_time_interval(dbuf, sizeof(dbuf), 9223372036854775807L);
+  tt_int_op(strnlen(dbuf, DBUF_SIZE),<=, DBUF_SIZE - 1);
+  r = tor_sscanf(dbuf, TL_ " " TL_ " " TL_,
+                 &day, label_d, &hour, label_h, &min, label_m);
+  tt_int_op(r,==, 6);
+  tt_int_op(day,==, 106751991167300L);
+  tt_ci_char_op(label_d[0],==, 'd');
+  tt_int_op(hour,==, 15);
+  tt_ci_char_op(label_h[0],==, 'h');
+  tt_int_op(min,==, 30);
+  tt_ci_char_op(label_m[0],==, 'm');
+  /* and 7 seconds - ignored */
+  
+  /* INT64_MIN: check that we get the absolute value of interval,
+   * which doesn't actually fit in int64_t.
+   * We expect INT64_MAX */
+  format_time_interval(dbuf, sizeof(dbuf),
+                       -9223372036854775807L - 1L);
+  tt_int_op(strnlen(dbuf, DBUF_SIZE),<=, DBUF_SIZE - 1);
+  r = tor_sscanf(dbuf, TL_ " " TL_ " " TL_,
+                 &day, label_d, &hour, label_h, &min, label_m);
+  tt_int_op(r,==, 6);
+  tt_int_op(day,==, 106751991167300L);
+  tt_ci_char_op(label_d[0],==, 'd');
+  tt_int_op(hour,==, 15);
+  tt_ci_char_op(label_h[0],==, 'h');
+  tt_int_op(min,==, 30);
+  tt_ci_char_op(label_m[0],==, 'm');
+  /* and 7 or 8 seconds - ignored */
+  
+#endif
+
+  
+done:
+  ;
+}
+
+#undef tt_char_op
+#undef tt_ci_char_op
+#undef DBUF_SIZE
+#undef T_
+#undef LABEL_SIZE
+#undef L_
+#undef TL_
+
 static void
 test_util_path_is_relative(void *arg)
 {
@@ -4146,6 +4568,7 @@ struct testcase_t util_tests[] = {
   UTIL_LEGACY(mmap),
   UTIL_LEGACY(threads),
   UTIL_LEGACY(sscanf),
+  UTIL_LEGACY(format_time_interval),
   UTIL_LEGACY(path_is_relative),
   UTIL_LEGACY(strtok),
   UTIL_LEGACY(di_ops),





More information about the tor-commits mailing list