[tor-commits] [tor/master] Fix tor_strtok_r_impl and test cases per bug #5091

nickm at torproject.org nickm at torproject.org
Fri May 11 15:49:35 UTC 2012


commit efb8a09f41fcd4c48bffdc98ae8d5e0002a0bb88
Author: nils <nils at shkoo.com>
Date:   Fri Mar 30 11:01:21 2012 -0400

    Fix tor_strtok_r_impl and test cases per bug #5091
    
    ==
    
    Nick here. I tweaked this patch a little to make it apply cleanly to
    master, to extract some common code into a function, and to replace
    snprintf with tor_snprintf.
    
    -- nickm
---
 changes/bug5091      |    4 +++
 src/common/compat.c  |   30 +++++++++++++++++----
 src/test/test_util.c |   70 ++++++++++++++++++++++++++++++++-----------------
 3 files changed, 74 insertions(+), 30 deletions(-)

diff --git a/changes/bug5091 b/changes/bug5091
new file mode 100644
index 0000000..b9778d7
--- /dev/null
+++ b/changes/bug5091
@@ -0,0 +1,4 @@
+  o Minor bugfixes:
+    - Make our replacement implementation of strtok_r compatible with
+      the standard behavior of strtok_r. Patch by nils. Fixes bug
+      5091; bugfix on 0.2.2.1-alpha.
diff --git a/src/common/compat.c b/src/common/compat.c
index 30bde3d..bd68225 100644
--- a/src/common/compat.c
+++ b/src/common/compat.c
@@ -546,25 +546,43 @@ const char TOR_TOLOWER_TABLE[256] = {
   240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255,
 };
 
+/** Helper for tor_strtok_r_impl: Advances cp past all characters in
+ * <b>sep</b>, and returns its new value. */
+static char *
+strtok_helper(char *cp, const char *sep)
+{
+  if (sep[1]) {
+    while (*cp && strchr(sep, *cp))
+      ++cp;
+  } else {
+    while (*cp && *cp == *sep)
+      ++cp;
+  }
+  return cp;
+}
+
 /** Implementation of strtok_r for platforms whose coders haven't figured out
  * how to write one.  Hey guys!  You can use this code here for free! */
 char *
 tor_strtok_r_impl(char *str, const char *sep, char **lasts)
 {
   char *cp, *start;
-  if (str)
+  tor_assert(*sep);
+  if (str) {
+    str = strtok_helper(str, sep);
+    if (!*str)
+      return NULL;
     start = cp = *lasts = str;
-  else if (!*lasts)
+  } else if (!*lasts || !**lasts) {
     return NULL;
-  else
+  } else {
     start = cp = *lasts;
+  }
 
-  tor_assert(*sep);
   if (sep[1]) {
     while (*cp && !strchr(sep, *cp))
       ++cp;
   } else {
-    tor_assert(strlen(sep) == 1);
     cp = strchr(cp, *sep);
   }
 
@@ -572,7 +590,7 @@ tor_strtok_r_impl(char *str, const char *sep, char **lasts)
     *lasts = NULL;
   } else {
     *cp++ = '\0';
-    *lasts = cp;
+    *lasts = strtok_helper(cp, sep);
   }
   return start;
 }
diff --git a/src/test/test_util.c b/src/test/test_util.c
index 88f00e0..3cbc5bf 100644
--- a/src/test/test_util.c
+++ b/src/test/test_util.c
@@ -1735,32 +1735,56 @@ test_util_strtok(void)
 {
   char buf[128];
   char buf2[128];
+  int i;
   char *cp1, *cp2;
-  strlcpy(buf, "Graved on the dark in gestures of descent", sizeof(buf));
-  strlcpy(buf2, "they.seemed;their!own;most.perfect;monument", sizeof(buf2));
-  /*  -- "Year's End", Richard Wilbur */
 
-  test_streq("Graved", tor_strtok_r_impl(buf, " ", &cp1));
-  test_streq("they", tor_strtok_r_impl(buf2, ".!..;!", &cp2));
+  for (i = 0; i < 3; i++) {
+    const char *pad1, *pad2;
+    switch (i) {
+    case 0:
+      pad1 = pad2 = "";
+      break;
+    case 1:
+      pad1 = " ";
+      pad2 = "!";
+      break;
+    case 2:
+      pad1 = "  ";
+      pad2 = ";!";
+      break;
+    }
+    tor_snprintf(buf, sizeof(buf), "%s", pad1);
+    tor_snprintf(buf2, sizeof(buf2), "%s", pad2);
+    test_assert(NULL == tor_strtok_r_impl(buf, " ", &cp1));
+    test_assert(NULL == tor_strtok_r_impl(buf2, ".!..;!", &cp2));
+
+    tor_snprintf(buf, sizeof(buf),
+                 "%sGraved on the dark  in gestures of descent%s", pad1, pad1);
+    tor_snprintf(buf2, sizeof(buf2),
+                 "%sthey.seemed;;their!.own;most.perfect;monument%s",pad2,pad2);
+    /*  -- "Year's End", Richard Wilbur */
+
+    test_streq("Graved", tor_strtok_r_impl(buf, " ", &cp1));
+    test_streq("they", tor_strtok_r_impl(buf2, ".!..;!", &cp2));
 #define S1() tor_strtok_r_impl(NULL, " ", &cp1)
 #define S2() tor_strtok_r_impl(NULL, ".!..;!", &cp2)
-  test_streq("on", S1());
-  test_streq("the", S1());
-  test_streq("dark", S1());
-  test_streq("seemed", S2());
-  test_streq("their", S2());
-  test_streq("own", S2());
-  test_streq("in", S1());
-  test_streq("gestures", S1());
-  test_streq("of", S1());
-  test_streq("most", S2());
-  test_streq("perfect", S2());
-  test_streq("descent", S1());
-  test_streq("monument", S2());
-  test_eq_ptr(NULL, S1());
-  test_eq_ptr(NULL, S2());
+    test_streq("on", S1());
+    test_streq("the", S1());
+    test_streq("dark", S1());
+    test_streq("seemed", S2());
+    test_streq("their", S2());
+    test_streq("own", S2());
+    test_streq("in", S1());
+    test_streq("gestures", S1());
+    test_streq("of", S1());
+    test_streq("most", S2());
+    test_streq("perfect", S2());
+    test_streq("descent", S1());
+    test_streq("monument", S2());
+    test_eq_ptr(NULL, S1());
+    test_eq_ptr(NULL, S2());
+  }
 
-#if 0
   buf[0] = 0;
   test_eq_ptr(NULL, tor_strtok_r_impl(buf, " ", &cp1));
   test_eq_ptr(NULL, tor_strtok_r_impl(buf, "!", &cp1));
@@ -1773,12 +1797,10 @@ test_util_strtok(void)
   test_eq_ptr(NULL, tor_strtok_r_impl(buf, " ", &cp1));
   strlcpy(buf, "  ", sizeof(buf));
   test_eq_ptr(NULL, tor_strtok_r_impl(buf, " ", &cp1));
-#endif
 
   strlcpy(buf, "something  ", sizeof(buf));
   test_streq("something", tor_strtok_r_impl(buf, " ", &cp1));
-  test_streq(" ", tor_strtok_r_impl(NULL, ";", &cp1));
-  test_eq_ptr(NULL, tor_strtok_r_impl(NULL, " ", &cp1));
+  test_eq_ptr(NULL, tor_strtok_r_impl(NULL, ";", &cp1));
  done:
   ;
 }





More information about the tor-commits mailing list