diff --git a/http.c b/http.c index a6d9ab3a..96c5305d 100644 --- a/http.c +++ b/http.c @@ -219,18 +219,25 @@ strsep(char **s, const char *del) } #endif -static void -rtrim(char *str) +void +evutil_rtrim_(char *str) { char *cp; - if( str == NULL ) + if (str == NULL) return; - cp = strchr(str, '\0') - 1; + if ((cp = strchr(str, '\0')) == NULL || (cp == str)) + return; - while (cp >= str && *cp == ' ') - *cp-- = '\0'; + --cp; + + while (*cp == ' ') { + *cp = '\0'; + if (cp == str) + break; + --cp; + } } static size_t @@ -1927,7 +1934,7 @@ evhttp_parse_headers_(struct evhttp_request *req, struct evbuffer* buffer) goto error; svalue += strspn(svalue, " "); - rtrim(svalue); + evutil_rtrim_(svalue); if (evhttp_add_header(headers, skey, svalue) == -1) goto error; diff --git a/test/regress_util.c b/test/regress_util.c index 41bc8184..2f20e942 100644 --- a/test/regress_util.c +++ b/test/regress_util.c @@ -434,6 +434,38 @@ end: ; } +static void +test_evutil_rtrim(void *ptr) +{ +#define TEST_TRIM(s, result) \ + do { \ + if (cp) mm_free(cp); \ + cp = s ? mm_strdup(s) : NULL; \ + evutil_rtrim_(cp); \ + if (result == NULL) \ + tt_ptr_op(cp, ==, NULL); \ + else \ + tt_str_op(cp, ==, result); \ + } while(0) + + char *cp = NULL; + (void) ptr; + + TEST_TRIM(NULL, NULL); + TEST_TRIM("", ""); + TEST_TRIM("a", "a"); + TEST_TRIM("abcdef ghi", "abcdef ghi"); + + TEST_TRIM(" ", ""); + TEST_TRIM(" ", ""); + TEST_TRIM("a ", "a"); + TEST_TRIM("abcdef gH ", "abcdef gH"); + +end: + if (cp) + mm_free(cp); +} + static int logsev = 0; static char *logmsg = NULL; @@ -1348,6 +1380,7 @@ struct testcase_t util_testcases[] = { { "evutil_snprintf", test_evutil_snprintf, 0, NULL, NULL }, { "evutil_strtoll", test_evutil_strtoll, 0, NULL, NULL }, { "evutil_casecmp", test_evutil_casecmp, 0, NULL, NULL }, + { "evutil_rtrim", test_evutil_rtrim, 0, NULL, NULL }, { "strlcpy", test_evutil_strlcpy, 0, NULL, NULL }, { "log", test_evutil_log, TT_FORK, NULL, NULL }, { "upcast", test_evutil_upcast, 0, NULL, NULL }, diff --git a/util-internal.h b/util-internal.h index da1fb838..dff3d70b 100644 --- a/util-internal.h +++ b/util-internal.h @@ -218,6 +218,10 @@ int EVUTIL_ISUPPER_(char c); char EVUTIL_TOUPPER_(char c); char EVUTIL_TOLOWER_(char c); +/** Remove all trailing whitespace from the end of a string */ +void evutil_rtrim_(char *); + + /** Helper macro. If we know that a given pointer points to a field in a structure, return a pointer to the structure itself. Used to implement our half-baked C OO. Example: