Clean up rtrim implementation

If I understand the C standard correctly, you can't actually point
at a position immediately _before_ the start of an object; only at the
position immediately after.

According to J.2 in the standard, in its big list of undefined behavior:

 "The behavior is undefined in the following circumstances:
     ...
   — Addition or subtraction of a pointer into, or just beyond, an
    array object and an integer type produces a result that does not
    point into, or just beyond, the same array object (6.5.6)."

So we've got to fix rtrim to not do that.  Also, make it unit tested,
and give it an evutil_*_ name.
This commit is contained in:
Nick Mathewson 2012-11-16 11:13:29 -05:00
parent 370a2c0213
commit aa59d805f5
3 changed files with 51 additions and 7 deletions

19
http.c
View File

@ -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)
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;

View File

@ -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 },

View File

@ -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: