Skip to content
Permalink
Browse files Browse the repository at this point in the history
Merge pull request #15929 from cgundogan/pr/uriparser
uri_parser: fix out-of-bounds and additional enhancements
  • Loading branch information
miri64 committed Feb 5, 2021
2 parents 07f1254 + 6ef29d9 commit bc59d60
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 15 deletions.
37 changes: 26 additions & 11 deletions sys/uri_parser/uri_parser.c
Expand Up @@ -75,9 +75,16 @@ void _consume_userinfo(uri_parser_result_t *result, char *uri,
if (userinfo_end) {
result->userinfo = uri;
result->userinfo_len = userinfo_end - uri;
/* shift host part beyond userinfo and '@' */
result->host += result->userinfo_len + 1;
result->host_len -= result->userinfo_len + 1;

/* shift host part beyond userinfo and '@', but only if possible */
unsigned offset = result->userinfo_len + 1;
if ((result->host + offset) > authority_end) {
result->host_len = 0;
return;
}

result->host_len -= offset;
result->host += offset;
}
}

Expand Down Expand Up @@ -125,6 +132,11 @@ static char *_consume_authority(uri_parser_result_t *result, char *uri,
/* consume userinfo, if available */
_consume_userinfo(result, uri, authority_end);

/* host is empty */
if (result->host_len == 0) {
return authority_end;
}

char *ipv6_end = NULL;
/* validate IPv6 form */
if (result->host[0] == '[') {
Expand Down Expand Up @@ -159,12 +171,6 @@ static char *_consume_authority(uri_parser_result_t *result, char *uri,
return NULL;
}

/* do not allow empty host if userinfo or port are set */
if ((result->host_len == 0) &&
(result->userinfo || result->port)) {
return NULL;
}

/* this includes the '/' */
return authority_end;
}
Expand Down Expand Up @@ -218,15 +224,24 @@ static int _parse_absolute(uri_parser_result_t *result, char *uri,
return -1;
}

if (uri >= uri_end) {
/* nothing more to consume */
return 0;
}

if (has_authority) {
uri = _consume_authority(result, uri, uri_end);
if (uri == NULL) {
return -1;
}
}

/* parsing the path, starting with '/' */
return _parse_relative(result, uri, uri_end);
/* is there more to parse after authority? */
if (uri < uri_end) {
/* parsing the path, starting with '/' */
return _parse_relative(result, uri, uri_end);
}
return 0;
}

bool uri_parser_is_absolute(const char *uri, size_t uri_len)
Expand Down
19 changes: 15 additions & 4 deletions tests/unittests/tests-uri_parser/tests-uri_parser.c
Expand Up @@ -216,15 +216,15 @@ static const validate_t validate_uris[] = {
0),
VEC("coap://R@////////////////7///v=1",
true,
"coap",
"R",
"",
"",
"",
"",
"////////////////7///v=1",
"",
"",
"",
"",
-1),
0),
VEC("coa[:////[2001:db5ow:5own/Ov=1",
false,
"",
Expand Down Expand Up @@ -412,6 +412,17 @@ static const validate_t validate_uris[] = {
"",
"",
0),
VEC("A://@",
true,
"A",
"",
"",
"",
"",
"",
"",
"",
0),
};

static char _failure_msg[VEC_MSG_LEN];
Expand Down

0 comments on commit bc59d60

Please sign in to comment.