Correct buffer over-read errors

When inserting multiple routes with common slug patterns
there are reads beyond end of strings.

The scenario is added as a testcase and can be triggered by
the address-sanitizer when built using:
`CFLAGS="-fno-omit-frame-pointer -fsanitize=address" cmake ..`

Indicated as a `buffer-overflow`
This commit is contained in:
Björn Svensson 2021-10-10 21:10:24 +02:00
parent d2fcf2f2d4
commit 00ec8b7f2b
3 changed files with 43 additions and 7 deletions

View file

@ -551,18 +551,16 @@ static r3_iovec_t* router_append_slug(R3Route * route, const char * slug, unsign
static void get_slugs(R3Route * route, const char * path, int path_len) {
const char *plh = path;
unsigned int l, namel;
l = 0;
const char *name;
unsigned int plhl, namel;
while (plh < (path + path_len)) {
plh = r3_slug_find_placeholder(plh+l, path_len, &l);
plh = r3_slug_find_placeholder(plh, path_len-(plh-path), &plhl);
if (!plh) break;
namel = 0;
name = r3_slug_find_name(plh, l, &namel);
name = r3_slug_find_name(plh, plhl, &namel);
if (name) {
router_append_slug(route, name, namel);
}
if ((plh + l) >= (path + path_len)) break;
plh += plhl;
}
}

View file

@ -86,7 +86,7 @@ int r3_slug_parse(r3_slug_t *s, const char *needle, int needle_len, const char *
}
// there is no slug
if (!r3_path_contains_slug_char(offset, needle_len)) {
if (!r3_path_contains_slug_char(offset, needle_len - (offset-needle))) {
return 0;
}

View file

@ -23,21 +23,58 @@ START_TEST (greedy_pattern)
matched_route = r3_tree_match_route(n, entry);
ck_assert(matched_route != NULL);
ck_assert(matched_route->data == &uri0);
match_entry_free(entry);
entry = match_entry_create("/foo");
matched_route = r3_tree_match_route(n, entry);
ck_assert(matched_route != NULL);
ck_assert(matched_route->data == &uri0);
match_entry_free(entry);
entry = match_entry_create("/foo/");
matched_route = r3_tree_match_route(n, entry);
ck_assert(matched_route != NULL);
ck_assert(matched_route->data == &uri0);
match_entry_free(entry);
entry = match_entry_create("/foo/bar/foo/mmasdfasdfasd/f/asdf/as/df");
matched_route = r3_tree_match_route(n, entry);
ck_assert(matched_route != NULL);
ck_assert(matched_route->data == &uri0);
match_entry_free(entry);
r3_tree_free(n);
}
END_TEST
START_TEST (common_pattern)
{
R3Node * n = r3_tree_create(10);
match_entry * entry;
R3Route *r, *matched_route;
char * uri0 = "/foo/{slug}";
r = r3_tree_insert_routel(n, 0, uri0, strlen(uri0), &uri0);
ck_assert(r != NULL);
char * uri1 = "/foo/{slug}/bar";
r = r3_tree_insert_routel(n, 0, uri1, strlen(uri1), &uri1);
ck_assert(r != NULL);
char * err = NULL;
r3_tree_compile(n, &err);
ck_assert(err == NULL);
entry = match_entry_create("/foo/bar");
matched_route = r3_tree_match_route(n, entry);
ck_assert(matched_route != NULL);
ck_assert(matched_route->data == &uri0);
match_entry_free(entry);
entry = match_entry_create("/foo/bar/bar");
matched_route = r3_tree_match_route(n, entry);
ck_assert(matched_route != NULL);
ck_assert(matched_route->data == &uri1);
match_entry_free(entry);
r3_tree_free(n);
}
@ -47,6 +84,7 @@ Suite* r3_suite (void) {
Suite *suite = suite_create("r3 routes2 tests");
TCase *tcase = tcase_create("testcase");
tcase_add_test(tcase, greedy_pattern);
tcase_add_test(tcase, common_pattern);
suite_add_tcase(suite, tcase);
return suite;
}