Commit 5ec3a733 authored by Tom McKee's avatar Tom McKee Committed by Commit Bot

Adding tests against and fixes for tabs in Server-Timing headers

According to the spec
(https://w3c.github.io/server-timing/#the-server-timing-header-field),
optional whitespace is allowed amongst parameter names and values. We
should be discarding this whitespace during parsing but, when there are
tabs, we were treating it like an error and discarding the whole value.

Changed the code that tokenizes HTTP headers to skip tabs and spaces
when consuming optional whitespace.

BUG=798446

Change-Id: If776761e5ea199e662ec7b2b5aa245e4581131fd
Reviewed-on: https://chromium-review.googlesource.com/1147258Reviewed-by: default avatarEmil A Eklund <eae@chromium.org>
Commit-Queue: Tom McKee <tommckee@chromium.org>
Cr-Commit-Position: refs/heads/master@{#577325}
parent db6633b3
testServerTiming(document.currentScript, [{"name":"metric", "desc":"tabs-should-get-trimmed", "dur": 42.0}])
This is a testharness.js-based test.
Found 324 tests; 322 PASS, 2 FAIL, 0 TIMEOUT, 0 NOTRUN.
Found 328 tests; 326 PASS, 2 FAIL, 0 TIMEOUT, 0 NOTRUN.
PASS 0.js - count (0 ?== 0)
PASS 1.js - count (1 ?== 1)
PASS 1.js - name (metric ?== metric)
......@@ -324,5 +324,9 @@ PASS 80.js - count (0 ?== 0)
PASS 81.js - count (0 ?== 0)
PASS 82.js - count (0 ?== 0)
PASS 83.js - count (0 ?== 0)
PASS 84.js - count (1 ?== 1)
PASS 84.js - name (metric ?== metric)
PASS 84.js - duration (42 ?== 42)
PASS 84.js - description (tabs-should-get-trimmed ?== tabs-should-get-trimmed)
Harness: the test ran to completion.
......@@ -43,7 +43,7 @@ tests generated by:
})
done()
}
for (let i = 0; i <= 83; i++) {
for (let i = 0; i <= 84; i++) {
const script = document.createElement('script')
script.src = `./resources/parsing/${i}.js`
document.getElementsByTagName('head')[0].appendChild(script)
......
......@@ -323,5 +323,9 @@ PASS 80.js - count (0 ?== 0)
PASS 81.js - count (0 ?== 0)
PASS 82.js - count (0 ?== 0)
PASS 83.js - count (0 ?== 0)
PASS 84.js - count (1 ?== 1)
PASS 84.js - name (metric ?== metric)
PASS 84.js - duration (42 ?== 42)
PASS 84.js - description (tabs-should-get-trimmed ?== tabs-should-get-trimmed)
Harness: the test ran to completion.
......@@ -43,7 +43,7 @@ tests generated by:
})
done()
}
for (let i = 0; i <= 83; i++) {
for (let i = 0; i <= 84; i++) {
const script = document.createElement('script')
script.src = `./resources/parsing/${i}.js`
document.getElementsByTagName('head')[0].appendChild(script)
......
......@@ -55,7 +55,7 @@ bool IsTokenCharacter(Mode mode, UChar c) {
HeaderFieldTokenizer::HeaderFieldTokenizer(const String& header_field)
: index_(0u), input_(header_field) {
SkipSpaces();
SkipOptionalWhitespace();
}
HeaderFieldTokenizer::HeaderFieldTokenizer(HeaderFieldTokenizer&&) = default;
......@@ -63,12 +63,13 @@ HeaderFieldTokenizer::HeaderFieldTokenizer(HeaderFieldTokenizer&&) = default;
bool HeaderFieldTokenizer::Consume(char c) {
// TODO(cvazac) change this to use LChar
DCHECK_NE(c, ' ');
DCHECK_NE(c, '\t');
if (IsConsumed() || input_[index_] != c)
return false;
++index_;
SkipSpaces();
SkipOptionalWhitespace();
return true;
}
......@@ -82,7 +83,7 @@ bool HeaderFieldTokenizer::ConsumeQuotedString(String& output) {
if (input_[index_] == '"') {
output = builder.ToString();
++index_;
SkipSpaces();
SkipOptionalWhitespace();
return true;
}
if (input_[index_] == '\\') {
......@@ -107,7 +108,7 @@ bool HeaderFieldTokenizer::ConsumeToken(Mode mode, StringView& output) {
return false;
output = StringView(input_, start, index_ - start);
SkipSpaces();
SkipOptionalWhitespace();
return true;
}
......@@ -126,10 +127,8 @@ bool HeaderFieldTokenizer::ConsumeTokenOrQuotedString(Mode mode,
return true;
}
void HeaderFieldTokenizer::SkipSpaces() {
// TODO(cvazac) skip tabs, per:
// https://tools.ietf.org/html/rfc7230#section-3.2.3
while (!IsConsumed() && input_[index_] == ' ')
void HeaderFieldTokenizer::SkipOptionalWhitespace() {
while (!IsConsumed() && (input_[index_] == ' ' || input_[index_] == '\t'))
++index_;
}
......
......@@ -41,7 +41,7 @@ class PLATFORM_EXPORT HeaderFieldTokenizer final {
private:
bool ConsumeQuotedString(String& output);
void SkipSpaces();
void SkipOptionalWhitespace();
unsigned index_;
const String input_;
......@@ -49,4 +49,4 @@ class PLATFORM_EXPORT HeaderFieldTokenizer final {
} // namespace blink
#endif
#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_NETWORK_HEADER_FIELD_TOKENIZER_H_
......@@ -35,21 +35,32 @@ void CheckValidity(bool expected,
TEST(ParsedContentHeaderFieldParametersTest, Validity) {
CheckValidity(true, "");
CheckValidity(true, " ");
CheckValidity(true, "\t");
CheckValidity(true, " ;p1=v1");
CheckValidity(true, "\t;p1=v1");
CheckValidity(true, "; p1=v1");
CheckValidity(true, ";\tp1=v1");
CheckValidity(true, ";p1=v1 ");
CheckValidity(true, ";p1=v1\t");
CheckValidity(true, ";p1 = v1");
CheckValidity(true, ";p1\t=\tv1");
CheckValidity(true, "; p1 = v1 ");
CheckValidity(true, ";\tp1\t=\tv1\t");
CheckValidity(true, ";z=\"ttx&r=z;;\\u\\\"kd==\"");
CheckValidity(true, "; z=\"\xff\"");
CheckValidity(false, "\r");
CheckValidity(false, "\n");
CheckValidity(false, " p1=v1");
CheckValidity(false, "\tp1=v1");
CheckValidity(false, ";p1=v1;");
CheckValidity(false, ";");
CheckValidity(false, "; ");
CheckValidity(false, ";\t");
CheckValidity(false, "; p1");
CheckValidity(false, ";\tp1");
CheckValidity(false, "; p1;");
CheckValidity(false, ";\tp1;");
CheckValidity(false, ";\"xx");
CheckValidity(false, ";\"xx=y");
CheckValidity(false, "; \"z\"=u");
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment