Browse Source

Merge remote-tracking branch 'origin/maint-0.2.2' into maint-0.2.3

Nick Mathewson 11 years ago
parent
commit
b0646cc142
3 changed files with 63 additions and 1 deletions
  1. 5 0
      changes/bug7191
  2. 22 1
      src/common/container.c
  3. 36 0
      src/test/test_containers.c

+ 5 - 0
changes/bug7191

@@ -0,0 +1,5 @@
+  o Major bugfixes:
+    - Fix a denial of service attack by which any directory authority
+      could crash all the others, or by which a single v2 directory
+      authority could crash everybody downloading v2 directory
+      information. Fixes bug 7191; bugfix on 0.2.0.10-alpha. 

+ 22 - 1
src/common/container.c

@@ -571,7 +571,28 @@ smartlist_bsearch_idx(const smartlist_t *sl, const void *key,
                       int (*compare)(const void *key, const void **member),
                       int *found_out)
 {
-  int hi = smartlist_len(sl) - 1, lo = 0, cmp, mid;
+  const int len = smartlist_len(sl);
+  int hi, lo, cmp, mid;
+
+  if (len == 0) {
+    *found_out = 0;
+    return 0;
+  } else if (len == 1) {
+    cmp = compare(key, (const void **) &sl->list[0]);
+    if (cmp == 0) {
+      *found_out = 1;
+      return 0;
+    } else if (cmp < 0) {
+      *found_out = 0;
+      return 0;
+    } else {
+      *found_out = 0;
+      return 1;
+    }
+  }
+
+  hi = smartlist_len(sl) - 1;
+  lo = 0;
 
   while (lo <= hi) {
     mid = (lo + hi) / 2;

+ 36 - 0
src/test/test_containers.c

@@ -16,6 +16,15 @@ _compare_strs(const void **a, const void **b)
   return strcmp(s1, s2);
 }
 
+/** Helper: return a tristate based on comparing the strings in <b>a</b> and
+ * *<b>b</b>. */
+static int
+compare_strs_for_bsearch_(const void *a, const void **b)
+{
+  const char *s1 = a, *s2 = *b;
+  return strcmp(s1, s2);
+}
+
 /** Helper: return a tristate based on comparing the strings in *<b>a</b> and
  * *<b>b</b>, excluding a's first character, and ignoring case. */
 static int
@@ -204,6 +213,8 @@ test_container_smartlist_strings(void)
   /* Test bsearch_idx */
   {
     int f;
+    smartlist_t *tmp = NULL;
+
     test_eq(0, smartlist_bsearch_idx(sl," aaa",_compare_without_first_ch,&f));
     test_eq(f, 0);
     test_eq(0, smartlist_bsearch_idx(sl," and",_compare_without_first_ch,&f));
@@ -216,6 +227,31 @@ test_container_smartlist_strings(void)
     test_eq(f, 0);
     test_eq(7, smartlist_bsearch_idx(sl," zzzz",_compare_without_first_ch,&f));
     test_eq(f, 0);
+
+    /* Test trivial cases for list of length 0 or 1 */
+    tmp = smartlist_create();
+    test_eq(0, smartlist_bsearch_idx(tmp, "foo",
+                                     compare_strs_for_bsearch_, &f));
+    test_eq(f, 0);
+    smartlist_insert(tmp, 0, (void *)("bar"));
+    test_eq(1, smartlist_bsearch_idx(tmp, "foo",
+                                     compare_strs_for_bsearch_, &f));
+    test_eq(f, 0);
+    test_eq(0, smartlist_bsearch_idx(tmp, "aaa",
+                                     compare_strs_for_bsearch_, &f));
+    test_eq(f, 0);
+    test_eq(0, smartlist_bsearch_idx(tmp, "bar",
+                                     compare_strs_for_bsearch_, &f));
+    test_eq(f, 1);
+    /* ... and one for length 2 */
+    smartlist_insert(tmp, 1, (void *)("foo"));
+    test_eq(1, smartlist_bsearch_idx(tmp, "foo",
+                                     compare_strs_for_bsearch_, &f));
+    test_eq(f, 1);
+    test_eq(2, smartlist_bsearch_idx(tmp, "goo",
+                                     compare_strs_for_bsearch_, &f));
+    test_eq(f, 0);
+    smartlist_free(tmp);
   }
 
   /* Test reverse() and pop_last() */