From 4414d7ef5718f93be107b4944fa49e9a5de212ca Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Tue, 7 Jun 2016 21:47:09 +0200 Subject: [PATCH] fix parse_token buffer overrun. missing tests for parse_token. this fixes http://bugs.eressea.de/view.php?id=2206 --- src/util/parser.c | 2 +- src/util/parser.test.c | 52 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 53 insertions(+), 1 deletion(-) diff --git a/src/util/parser.c b/src/util/parser.c index 63b293e82..741fd573f 100644 --- a/src/util/parser.c +++ b/src/util/parser.c @@ -192,7 +192,7 @@ char *parse_token(const char **str, char *lbuf, size_t buflen) copy = true; } if (copy) { - if (cursor - buflen < lbuf - 1) { + if (cursor - buflen < lbuf - len) { memcpy(cursor, ctoken, len); cursor += len; } diff --git a/src/util/parser.test.c b/src/util/parser.test.c index 95ef70a17..3c60fee54 100644 --- a/src/util/parser.test.c +++ b/src/util/parser.test.c @@ -3,6 +3,55 @@ #include +static void test_parse_token(CuTest *tc) { + char lbuf[8]; + const char *tok; + const char *str, *orig; + + orig = str = "SHORT TOKEN"; + tok = parse_token(&str, lbuf, sizeof(lbuf)); + CuAssertPtrEquals(tc, (void *)(orig+5), (void *)str); + CuAssertStrEquals(tc, "SHORT", tok); + tok = parse_token(&str, lbuf, sizeof(lbuf)); + CuAssertPtrEquals(tc, (void *)(orig + 11), (void *)str); + CuAssertStrEquals(tc, "TOKEN", tok); + tok = parse_token(&str, lbuf, sizeof(lbuf)); + CuAssertPtrEquals(tc, NULL, (void *)tok); +} + +static void test_parse_token_limit(CuTest *tc) { + char lbuf[8]; + const char *tok; + const char *str, *orig; + + orig = str = "LONG_TOKEN"; + tok = parse_token(&str, lbuf, sizeof(lbuf)); + CuAssertPtrEquals(tc, (void *)(orig + 10), (void *)str); + CuAssertStrEquals(tc, tok, "LONG_TO"); + tok = parse_token(&str, lbuf, sizeof(lbuf)); + CuAssertPtrEquals(tc, NULL, (void *)tok); +} + +static void test_parse_token_limit_utf8(CuTest *tc) { + char lbuf[8]; + const char *tok; + const char *orig = "a\xc3\xa4\xc3\xb6\xc3\xbc\xc3\x9f"; /* auml ouml uuml szlig, 8 bytes long */ + const char *str = orig+1; + + tok = parse_token(&str, lbuf, sizeof(lbuf)); + CuAssertPtrEquals(tc, (void *)(orig + strlen(orig)), (void *)str); + CuAssertStrEquals(tc, tok, "\xc3\xa4\xc3\xb6\xc3\xbc"); // just three letters fit, 6 bytes long + tok = parse_token(&str, lbuf, sizeof(lbuf)); + CuAssertPtrEquals(tc, NULL, (void *)tok); + + str = orig; // now with an extra byte in the front, maxing out lbuf exactly + tok = parse_token(&str, lbuf, sizeof(lbuf)); + CuAssertPtrEquals(tc, (void *)(orig + strlen(orig)), (void *)str); + CuAssertStrEquals(tc, tok, "a\xc3\xa4\xc3\xb6\xc3\xbc"); + tok = parse_token(&str, lbuf, sizeof(lbuf)); + CuAssertPtrEquals(tc, NULL, (void *)tok); +} + static void test_gettoken(CuTest *tc) { char token[128]; init_tokens_str("HELP ONE TWO THREE"); @@ -64,6 +113,9 @@ CuSuite *get_parser_suite(void) CuSuite *suite = CuSuiteNew(); SUITE_ADD_TEST(suite, test_atoip); SUITE_ADD_TEST(suite, test_skip_token); + SUITE_ADD_TEST(suite, test_parse_token); + SUITE_ADD_TEST(suite, test_parse_token_limit); + SUITE_ADD_TEST(suite, test_parse_token_limit_utf8); SUITE_ADD_TEST(suite, test_gettoken); SUITE_ADD_TEST(suite, test_gettoken_short); SUITE_ADD_TEST(suite, test_getintegers);