[tor-commits] [tor/master] Extract the common body of our random-int functions into a macro

dgoulet at torproject.org dgoulet at torproject.org
Thu Feb 14 16:48:44 UTC 2019


commit 622a9a8a364520f2f1d0294b8d4389f1b29ba376
Author: Nick Mathewson <nickm at torproject.org>
Date:   Wed Feb 6 12:51:50 2019 -0500

    Extract the common body of our random-int functions into a macro
    
    This is the second part of refactoring the random-int-in-range code.
---
 src/lib/crypt_ops/crypto_rand_numeric.c | 67 ++++++++++++++++++++-------------
 1 file changed, 40 insertions(+), 27 deletions(-)

diff --git a/src/lib/crypt_ops/crypto_rand_numeric.c b/src/lib/crypt_ops/crypto_rand_numeric.c
index 97fe3bd18..d07657440 100644
--- a/src/lib/crypt_ops/crypto_rand_numeric.c
+++ b/src/lib/crypt_ops/crypto_rand_numeric.c
@@ -9,6 +9,39 @@
 #include "lib/log/util_bug.h"
 
 /**
+ * Implementation macro: yields code that returns a uniform unbiased
+ * random number between 0 and limit.  "type" is the type of the number to
+ * return; "maxval" is the largest possible value of "type"; and "fill_stmt"
+ * is a code snippet that fills an object named "val" with random bits.
+ **/
+#define IMPLEMENT_RAND_UNSIGNED(type, maxval, limit, fill_stmt)         \
+  do {                                                                  \
+    type val;                                                           \
+    type cutoff;                                                        \
+    tor_assert((limit) > 0);                                            \
+                                                                        \
+    /* We ignore any values that are >= 'cutoff,' to avoid biasing */   \
+    /* the distribution with clipping at the upper end of the type's */ \
+    /* range. */                                                        \
+    cutoff = (maxval) - ((maxval)%(limit));                             \
+    while (1) {                                                         \
+      fill_stmt;                                                        \
+      if (val < cutoff)                                                 \
+        return val % (limit);                                           \
+    }                                                                   \
+  } while (0)
+
+/** Helper: Return a pseudorandom integer chosen uniformly from the
+ * values between 0 and limit-1 inclusive. */
+static unsigned
+crypto_rand_uint(unsigned limit)
+{
+  tor_assert(limit < UINT_MAX);
+  IMPLEMENT_RAND_UNSIGNED(unsigned, UINT_MAX, limit,
+                          crypto_rand((char*)&val, sizeof(val)));
+}
+
+/**
  * Return a pseudorandom integer, chosen uniformly from the values
  * between 0 and <b>max</b>-1 inclusive.  <b>max</b> must be between 1 and
  * INT_MAX+1, inclusive.
@@ -16,21 +49,13 @@
 int
 crypto_rand_int(unsigned int max)
 {
-  unsigned int val;
-  unsigned int cutoff;
+  /* We can't use IMPLEMENT_RAND_UNSIGNED directly, since we're trying
+   * to return a signed type. Instead we make sure that the range is
+   * reasonable for a nonnegative int, use crypto_rand_uint(), and cast.
+   */
   tor_assert(max <= ((unsigned int)INT_MAX)+1);
-  tor_assert(max > 0); /* don't div by 0 */
 
-  /* We ignore any values that are >= 'cutoff,' to avoid biasing the
-   * distribution with clipping at the upper end of unsigned int's
-   * range.
-   */
-  cutoff = UINT_MAX - (UINT_MAX%max);
-  while (1) {
-    crypto_rand((char*)&val, sizeof(val));
-    if (val < cutoff)
-      return val % max;
-  }
+  return (int)crypto_rand_uint(max);
 }
 
 /**
@@ -78,21 +103,9 @@ crypto_rand_time_range(time_t min, time_t max)
 uint64_t
 crypto_rand_uint64(uint64_t max)
 {
-  uint64_t val;
-  uint64_t cutoff;
   tor_assert(max < UINT64_MAX);
-  tor_assert(max > 0); /* don't div by 0 */
-
-  /* We ignore any values that are >= 'cutoff,' to avoid biasing the
-   * distribution with clipping at the upper end of unsigned int's
-   * range.
-   */
-  cutoff = UINT64_MAX - (UINT64_MAX%max);
-  while (1) {
-    crypto_rand((char*)&val, sizeof(val));
-    if (val < cutoff)
-      return val % max;
-  }
+  IMPLEMENT_RAND_UNSIGNED(uint64_t, UINT64_MAX, max,
+                          crypto_rand((char*)&val, sizeof(val)));
 }
 
 /**





More information about the tor-commits mailing list