diff --git a/changes/bug5091 b/changes/bug5091 new file mode 100644 index 0000000000..b9778d7b1e --- /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 57fc021f35..1680f66f2a 100644 --- a/src/common/compat.c +++ b/src/common/compat.c @@ -554,25 +554,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 + * sep, 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) - start = cp = *lasts = str; - else if (!*lasts) - return NULL; - else - start = cp = *lasts; - tor_assert(*sep); + if (str) { + str = strtok_helper(str, sep); + if (!*str) + return NULL; + start = cp = *lasts = str; + } else if (!*lasts || !**lasts) { + return NULL; + } else { + start = cp = *lasts; + } + if (sep[1]) { while (*cp && !strchr(sep, *cp)) ++cp; } else { - tor_assert(strlen(sep) == 1); cp = strchr(cp, *sep); } @@ -580,7 +598,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 e8f043a2c5..365b5ac772 100644 --- a/src/test/test_util.c +++ b/src/test/test_util.c @@ -1752,32 +1752,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)); @@ -1790,12 +1814,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: ; }