From 7451a73defc84376807e59420f89eed9686d1512 Mon Sep 17 00:00:00 2001 From: Tatsuhiro Tsujikawa Date: Sun, 12 Apr 2015 17:42:25 +0900 Subject: [PATCH] nghttpx: Don't push resource if link header has non empty loadpolicy --- src/http2.cc | 47 +++++++++++++++++++++++++++++++++++------------ src/http2_test.cc | 13 +++++++++++++ 2 files changed, 48 insertions(+), 12 deletions(-) diff --git a/src/http2.cc b/src/http2.cc index 5fc50683..26e61cbf 100644 --- a/src/http2.cc +++ b/src/http2.cc @@ -718,6 +718,30 @@ InputIt skip_to_right_dquote(InputIt first, InputIt last) { } } // namespace +namespace { +// Returns true if link-param does not match pattern |pat| of length +// |patlen| or it has empty value (""). |pat| should be parmname +// followed by "=". +bool check_link_param_empty(const char *first, const char *last, + const char *pat, size_t patlen) { + if (first + patlen <= last) { + if (std::equal(pat, pat + patlen, first, util::CaseCmp())) { + // we only accept URI if pat is followd by "" (e.g., + // loadpolicy="") here. + if (first + patlen + 2 <= last) { + if (*(first + patlen) != '"' || *(first + patlen + 1) != '"') { + return false; + } + } else { + // here we got invalid production (anchor=") or anchor=? + return false; + } + } + } + return true; +} +} // namespace + namespace { std::pair parse_next_link_header_once(const char *first, const char *last) { @@ -836,18 +860,17 @@ parse_next_link_header_once(const char *first, const char *last) { // we have to reject URI if we have nonempty anchor parameter. static const char ANCHOR[] = "anchor="; static const size_t ANCHORLEN = sizeof(ANCHOR) - 1; - if (!ign && first + ANCHORLEN <= last) { - if (std::equal(ANCHOR, ANCHOR + ANCHORLEN, first, util::CaseCmp())) { - // we only accept URI if anchor="" here. - if (first + ANCHORLEN + 2 <= last) { - if (*(first + ANCHORLEN) != '"' || *(first + ANCHORLEN + 1) != '"') { - ign = true; - } - } else { - // here we got invalid production (anchor=") or anchor=? - ign = true; - } - } + if (!ign && !check_link_param_empty(first, last, ANCHOR, ANCHORLEN)) { + ign = true; + } + + // reject URI if we have non-empty loadpolicy. This could be + // tightened up to just pick up "next" or "insert". + static const char LOADPOLICY[] = "loadpolicy="; + static const size_t LOADPOLICYLEN = sizeof(LOADPOLICY) - 1; + if (!ign && + !check_link_param_empty(first, last, LOADPOLICY, LOADPOLICYLEN)) { + ign = true; } auto param_first = first; diff --git a/src/http2_test.cc b/src/http2_test.cc index 01a2bc50..e2975d1f 100644 --- a/src/http2_test.cc +++ b/src/http2_test.cc @@ -627,6 +627,19 @@ void test_http2_parse_link_header(void) { CU_ASSERT(1 == res.size()); CU_ASSERT(std::make_pair(&s[36], &s[39]) == res[0].uri); } + { + // With loadpolicy="next", url should be ignored + const char s[] = R"(; rel=preload; loadpolicy="next")"; + auto res = http2::parse_link_header(s, sizeof(s) - 1); + CU_ASSERT(0 == res.size()); + } + { + // url should be picked up if empty loadpolicy is specified + const char s[] = R"(; rel=preload; loadpolicy="")"; + auto res = http2::parse_link_header(s, sizeof(s) - 1); + CU_ASSERT(1 == res.size()); + CU_ASSERT(std::make_pair(&s[1], &s[4]) == res[0].uri); + } { // case-insensitive match const char s[] = R"(; rel=preload; ANCHOR="#foo", ; )"