Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(95)

Side by Side Diff: net/http/http_util.cc

Issue 2225933004: Avoid adding invalid headers in AddHeaderFromString (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Rebase Created 4 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « net/http/http_util.h ('k') | net/http/http_util_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 // The rules for parsing content-types were borrowed from Firefox: 5 // The rules for parsing content-types were borrowed from Firefox:
6 // http://lxr.mozilla.org/mozilla/source/netwerk/base/src/nsURLHelper.cpp#834 6 // http://lxr.mozilla.org/mozilla/source/netwerk/base/src/nsURLHelper.cpp#834
7 7
8 #include "net/http/http_util.h" 8 #include "net/http/http_util.h"
9 9
10 #include <algorithm> 10 #include <algorithm>
11 11
12 #include "base/logging.h" 12 #include "base/logging.h"
13 #include "base/strings/string_number_conversions.h" 13 #include "base/strings/string_number_conversions.h"
14 #include "base/strings/string_piece.h" 14 #include "base/strings/string_piece.h"
15 #include "base/strings/string_tokenizer.h" 15 #include "base/strings/string_tokenizer.h"
16 #include "base/strings/string_util.h" 16 #include "base/strings/string_util.h"
17 #include "base/strings/stringprintf.h" 17 #include "base/strings/stringprintf.h"
18 #include "base/time/time.h" 18 #include "base/time/time.h"
19 #include "net/base/url_util.h" 19 #include "net/base/url_util.h"
20 20
21 namespace net { 21 namespace net {
22 22
23 namespace {
24 template <typename ConstIterator>
25 void TrimLWSImplementation(ConstIterator* begin, ConstIterator* end) {
26 // leading whitespace
27 while (*begin < *end && HttpUtil::IsLWS((*begin)[0]))
28 ++(*begin);
29
30 // trailing whitespace
31 while (*begin < *end && HttpUtil::IsLWS((*end)[-1]))
32 --(*end);
33 }
34 } // namespace
35
23 // Helpers -------------------------------------------------------------------- 36 // Helpers --------------------------------------------------------------------
24 37
25 // Returns the index of the closing quote of the string, if any. |start| points 38 // Returns the index of the closing quote of the string, if any. |start| points
26 // at the opening quote. 39 // at the opening quote.
27 static size_t FindStringEnd(const std::string& line, size_t start, char delim) { 40 static size_t FindStringEnd(const std::string& line, size_t start, char delim) {
28 DCHECK_LT(start, line.length()); 41 DCHECK_LT(start, line.length());
29 DCHECK_EQ(line[start], delim); 42 DCHECK_EQ(line[start], delim);
30 DCHECK((delim == '"') || (delim == '\'')); 43 DCHECK((delim == '"') || (delim == '\''));
31 44
32 const char set[] = { delim, '\\', '\0' }; 45 const char set[] = { delim, '\\', '\0' };
(...skipping 300 matching lines...) Expand 10 before | Expand all | Expand 10 after
333 base::StartsWith(lower_name, "sec-", base::CompareCase::SENSITIVE)) 346 base::StartsWith(lower_name, "sec-", base::CompareCase::SENSITIVE))
334 return false; 347 return false;
335 for (size_t i = 0; i < arraysize(kForbiddenHeaderFields); ++i) { 348 for (size_t i = 0; i < arraysize(kForbiddenHeaderFields); ++i) {
336 if (lower_name == kForbiddenHeaderFields[i]) 349 if (lower_name == kForbiddenHeaderFields[i])
337 return false; 350 return false;
338 } 351 }
339 return true; 352 return true;
340 } 353 }
341 354
342 // static 355 // static
343 bool HttpUtil::IsValidHeaderName(const std::string& name) { 356 bool HttpUtil::IsValidHeaderName(const base::StringPiece& name) {
344 // Check whether the header name is RFC 2616-compliant. 357 // Check whether the header name is RFC 2616-compliant.
345 return HttpUtil::IsToken(name); 358 return HttpUtil::IsToken(name);
346 } 359 }
347 360
348 // static 361 // static
349 bool HttpUtil::IsValidHeaderValue(const std::string& value) { 362 bool HttpUtil::IsValidHeaderValue(const base::StringPiece& value) {
350 // Just a sanity check: disallow NUL, CR and LF. 363 // Just a sanity check: disallow NUL, CR and LF.
351 return value.find_first_of("\0\r\n", 0, 3) == std::string::npos; 364 for (char c : value) {
365 if (c == '\0' || c == '\r' || c == '\n')
366 return false;
367 }
368 return true;
352 } 369 }
353 370
354 // static 371 // static
355 std::string HttpUtil::StripHeaders(const std::string& headers, 372 std::string HttpUtil::StripHeaders(const std::string& headers,
356 const char* const headers_to_remove[], 373 const char* const headers_to_remove[],
357 size_t headers_to_remove_len) { 374 size_t headers_to_remove_len) {
358 std::string stripped_headers; 375 std::string stripped_headers;
359 HttpUtil::HeadersIterator it(headers.begin(), headers.end(), "\r\n"); 376 HttpUtil::HeadersIterator it(headers.begin(), headers.end(), "\r\n");
360 377
361 while (it.GetNext()) { 378 while (it.GetNext()) {
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
402 kNonCoalescingHeaders[i])) 419 kNonCoalescingHeaders[i]))
403 return true; 420 return true;
404 } 421 }
405 return false; 422 return false;
406 } 423 }
407 424
408 bool HttpUtil::IsLWS(char c) { 425 bool HttpUtil::IsLWS(char c) {
409 return strchr(HTTP_LWS, c) != NULL; 426 return strchr(HTTP_LWS, c) != NULL;
410 } 427 }
411 428
429 // static
412 void HttpUtil::TrimLWS(std::string::const_iterator* begin, 430 void HttpUtil::TrimLWS(std::string::const_iterator* begin,
413 std::string::const_iterator* end) { 431 std::string::const_iterator* end) {
414 // leading whitespace 432 TrimLWSImplementation(begin, end);
415 while (*begin < *end && IsLWS((*begin)[0])) 433 }
416 ++(*begin);
417 434
418 // trailing whitespace 435 // static
419 while (*begin < *end && IsLWS((*end)[-1])) 436 base::StringPiece HttpUtil::TrimLWS(const base::StringPiece& string) {
420 --(*end); 437 const char* begin = string.data();
438 const char* end = string.data() + string.size();
439 TrimLWSImplementation(&begin, &end);
440 return base::StringPiece(begin, end - begin);
421 } 441 }
422 442
423 bool HttpUtil::IsQuote(char c) { 443 bool HttpUtil::IsQuote(char c) {
424 // Single quote mark isn't actually part of quoted-text production, 444 // Single quote mark isn't actually part of quoted-text production,
425 // but apparently some servers rely on this. 445 // but apparently some servers rely on this.
426 return c == '"' || c == '\''; 446 return c == '"' || c == '\'';
427 } 447 }
428 448
429 namespace { 449 namespace {
430 bool IsTokenChar(unsigned char c) { 450 bool IsTokenChar(unsigned char c) {
431 return !(c >= 0x80 || c <= 0x1F || c == 0x7F || c == '(' || c == ')' || 451 return !(c >= 0x80 || c <= 0x1F || c == 0x7F || c == '(' || c == ')' ||
432 c == '<' || c == '>' || c == '@' || c == ',' || c == ';' || 452 c == '<' || c == '>' || c == '@' || c == ',' || c == ';' ||
433 c == ':' || c == '\\' || c == '"' || c == '/' || c == '[' || 453 c == ':' || c == '\\' || c == '"' || c == '/' || c == '[' ||
434 c == ']' || c == '?' || c == '=' || c == '{' || c == '}' || 454 c == ']' || c == '?' || c == '=' || c == '{' || c == '}' ||
435 c == ' ' || c == '\t'); 455 c == ' ' || c == '\t');
436 } 456 }
437 } // anonymous namespace 457 } // anonymous namespace
438 458
439 // See RFC 2616 Sec 2.2 for the definition of |token|. 459 // See RFC 2616 Sec 2.2 for the definition of |token|.
440 bool HttpUtil::IsToken(std::string::const_iterator begin, 460 bool HttpUtil::IsToken(const base::StringPiece& string) {
441 std::string::const_iterator end) { 461 if (string.empty())
442 if (begin == end)
443 return false; 462 return false;
444 for (std::string::const_iterator iter = begin; iter != end; ++iter) { 463 for (char c : string) {
445 if (!IsTokenChar(*iter)) 464 if (!IsTokenChar(c))
446 return false; 465 return false;
447 } 466 }
448 return true; 467 return true;
449 } 468 }
450 469
451 // See RFC 5987 Sec 3.2.1 for the definition of |parmname|. 470 // See RFC 5987 Sec 3.2.1 for the definition of |parmname|.
452 bool HttpUtil::IsParmName(std::string::const_iterator begin, 471 bool HttpUtil::IsParmName(std::string::const_iterator begin,
453 std::string::const_iterator end) { 472 std::string::const_iterator end) {
454 if (begin == end) 473 if (begin == end)
455 return false; 474 return false;
(...skipping 428 matching lines...) Expand 10 before | Expand all | Expand 10 after
884 903
885 name_end_ = colon; 904 name_end_ = colon;
886 905
887 // If the name starts with LWS, it is an invalid line. 906 // If the name starts with LWS, it is an invalid line.
888 // Leading LWS implies a line continuation, and these should have 907 // Leading LWS implies a line continuation, and these should have
889 // already been joined by AssembleRawHeaders(). 908 // already been joined by AssembleRawHeaders().
890 if (name_begin_ == name_end_ || IsLWS(*name_begin_)) 909 if (name_begin_ == name_end_ || IsLWS(*name_begin_))
891 continue; 910 continue;
892 911
893 TrimLWS(&name_begin_, &name_end_); 912 TrimLWS(&name_begin_, &name_end_);
894 if (!IsToken(name_begin_, name_end_)) 913 DCHECK(name_begin_ < name_end_);
914 if (!IsToken(base::StringPiece(name_begin_, name_end_)))
895 continue; // skip malformed header 915 continue; // skip malformed header
896 916
897 values_begin_ = colon + 1; 917 values_begin_ = colon + 1;
898 TrimLWS(&values_begin_, &values_end_); 918 TrimLWS(&values_begin_, &values_end_);
899 919
900 // if we got a header name, then we are done. 920 // if we got a header name, then we are done.
901 return true; 921 return true;
902 } 922 }
903 return false; 923 return false;
904 } 924 }
(...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after
1053 return true; 1073 return true;
1054 } 1074 }
1055 1075
1056 bool HttpUtil::NameValuePairsIterator::IsQuote(char c) const { 1076 bool HttpUtil::NameValuePairsIterator::IsQuote(char c) const {
1057 if (strict_quotes_) 1077 if (strict_quotes_)
1058 return c == '"'; 1078 return c == '"';
1059 return HttpUtil::IsQuote(c); 1079 return HttpUtil::IsQuote(c);
1060 } 1080 }
1061 1081
1062 } // namespace net 1082 } // namespace net
OLDNEW
« no previous file with comments | « net/http/http_util.h ('k') | net/http/http_util_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698