diff --git a/src/http2.cc b/src/http2.cc index e492b759..6bb0ba4d 100644 --- a/src/http2.cc +++ b/src/http2.cc @@ -759,26 +759,32 @@ parse_next_link_header_once(const char *first, const char *last) { // we are only interested in rel=preload parameter. Others are // simply skipped. static const char PL[] = "rel=preload"; - if (last - first >= sizeof(PL) - 1) { - if (memcmp(PL, first, sizeof(PL) - 1) == 0) { - if (first + sizeof(PL) - 1 == last) { - ok = true; - // this is the end of sequence - return {{{url_first, url_last}}, last}; + static const size_t PLLEN = sizeof(PL) - 1; + if (first + PLLEN == last) { + if (std::equal(PL, PL + PLLEN, first)) { + ok = true; + // this is the end of sequence + return {{{url_first, url_last}}, last}; + } + } else if (first + PLLEN + 1 <= last) { + switch (*(first + PLLEN)) { + case ',': + if (!std::equal(PL, PL + PLLEN, first)) { + break; } - switch (*(first + sizeof(PL) - 1)) { - case ',': - ok = true; - // skip including ',' - first += sizeof(PL); - return {{{url_first, url_last}}, first}; - case ';': - ok = true; - // skip including ';' - first += sizeof(PL); - // continue parse next link-param - continue; + ok = true; + // skip including ',' + first += PLLEN + 1; + return {{{url_first, url_last}}, first}; + case ';': + if (!std::equal(PL, PL + PLLEN, first)) { + break; } + ok = true; + // skip including ';' + first += PLLEN + 1; + // continue parse next link-param + continue; } } auto param_first = first; diff --git a/src/http2_test.cc b/src/http2_test.cc index 2c2ffcd7..46bccdf5 100644 --- a/src/http2_test.cc +++ b/src/http2_test.cc @@ -479,6 +479,12 @@ void test_http2_parse_link_header(void) { CU_ASSERT(1 == res.size()); CU_ASSERT(std::make_pair(&s[3], &s[6]) == res[0].uri); } + { + // preload is a prefix of bogus rel parameter value + const char s[] = "; rel=preloadx"; + auto res = http2::parse_link_header(s, sizeof(s) - 1); + CU_ASSERT(0 == res.size()); + } } void test_http2_path_join(void) {