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:
parent
d2fcf2f2d4
commit
00ec8b7f2b
3 changed files with 43 additions and 7 deletions
10
src/node.c
10
src/node.c
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue