OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 2011 Google, Inc. All rights reserved. | 2 * Copyright (C) 2011 Google, Inc. All rights reserved. |
3 * | 3 * |
4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
5 * modification, are permitted provided that the following conditions | 5 * modification, are permitted provided that the following conditions |
6 * are met: | 6 * are met: |
7 * 1. Redistributions of source code must retain the above copyright | 7 * 1. Redistributions of source code must retain the above copyright |
8 * notice, this list of conditions and the following disclaimer. | 8 * notice, this list of conditions and the following disclaimer. |
9 * 2. Redistributions in binary form must reproduce the above copyright | 9 * 2. Redistributions in binary form must reproduce the above copyright |
10 * notice, this list of conditions and the following disclaimer in the | 10 * notice, this list of conditions and the following disclaimer in the |
(...skipping 23 matching lines...) Expand all Loading... |
34 #include "core/dom/Document.h" | 34 #include "core/dom/Document.h" |
35 #include "core/dom/SecurityPolicyViolationEvent.h" | 35 #include "core/dom/SecurityPolicyViolationEvent.h" |
36 #include "core/inspector/InspectorInstrumentation.h" | 36 #include "core/inspector/InspectorInstrumentation.h" |
37 #include "core/inspector/ScriptCallStack.h" | 37 #include "core/inspector/ScriptCallStack.h" |
38 #include "core/loader/DocumentLoader.h" | 38 #include "core/loader/DocumentLoader.h" |
39 #include "core/loader/PingLoader.h" | 39 #include "core/loader/PingLoader.h" |
40 #include "core/page/ContentSecurityPolicyResponseHeaders.h" | 40 #include "core/page/ContentSecurityPolicyResponseHeaders.h" |
41 #include "core/page/Frame.h" | 41 #include "core/page/Frame.h" |
42 #include "core/page/UseCounter.h" | 42 #include "core/page/UseCounter.h" |
43 #include "core/platform/JSONValues.h" | 43 #include "core/platform/JSONValues.h" |
| 44 #include "core/platform/ParsingUtilities.h" |
44 #include "core/platform/network/FormData.h" | 45 #include "core/platform/network/FormData.h" |
45 #include "core/platform/network/ResourceResponse.h" | 46 #include "core/platform/network/ResourceResponse.h" |
46 #include "weborigin/KURL.h" | 47 #include "weborigin/KURL.h" |
47 #include "weborigin/KnownPorts.h" | 48 #include "weborigin/KnownPorts.h" |
48 #include "weborigin/SchemeRegistry.h" | 49 #include "weborigin/SchemeRegistry.h" |
49 #include "weborigin/SecurityOrigin.h" | 50 #include "weborigin/SecurityOrigin.h" |
50 #include "wtf/HashSet.h" | 51 #include "wtf/HashSet.h" |
51 #include "wtf/text/TextPosition.h" | 52 #include "wtf/text/TextPosition.h" |
52 #include "wtf/text/WTFString.h" | 53 #include "wtf/text/WTFString.h" |
53 | 54 |
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
158 return UseCounter::PrefixedContentSecurityPolicyReportOnly; | 159 return UseCounter::PrefixedContentSecurityPolicyReportOnly; |
159 case ContentSecurityPolicy::Report: | 160 case ContentSecurityPolicy::Report: |
160 return UseCounter::ContentSecurityPolicyReportOnly; | 161 return UseCounter::ContentSecurityPolicyReportOnly; |
161 } | 162 } |
162 ASSERT_NOT_REACHED(); | 163 ASSERT_NOT_REACHED(); |
163 return UseCounter::NumberOfFeatures; | 164 return UseCounter::NumberOfFeatures; |
164 } | 165 } |
165 | 166 |
166 } // namespace | 167 } // namespace |
167 | 168 |
168 static bool skipExactly(const UChar*& position, const UChar* end, UChar delimite
r) | |
169 { | |
170 if (position < end && *position == delimiter) { | |
171 ++position; | |
172 return true; | |
173 } | |
174 return false; | |
175 } | |
176 | |
177 template<bool characterPredicate(UChar)> | |
178 static bool skipExactly(const UChar*& position, const UChar* end) | |
179 { | |
180 if (position < end && characterPredicate(*position)) { | |
181 ++position; | |
182 return true; | |
183 } | |
184 return false; | |
185 } | |
186 | |
187 static void skipUntil(const UChar*& position, const UChar* end, UChar delimiter) | |
188 { | |
189 while (position < end && *position != delimiter) | |
190 ++position; | |
191 } | |
192 | |
193 template<bool characterPredicate(UChar)> | |
194 static void skipWhile(const UChar*& position, const UChar* end) | |
195 { | |
196 while (position < end && characterPredicate(*position)) | |
197 ++position; | |
198 } | |
199 | |
200 static bool isSourceListNone(const UChar* begin, const UChar* end) | 169 static bool isSourceListNone(const UChar* begin, const UChar* end) |
201 { | 170 { |
202 skipWhile<isASCIISpace>(begin, end); | 171 skipWhile<UChar, isASCIISpace>(begin, end); |
203 | 172 |
204 const UChar* position = begin; | 173 const UChar* position = begin; |
205 skipWhile<isSourceCharacter>(position, end); | 174 skipWhile<UChar, isSourceCharacter>(position, end); |
206 if (!equalIgnoringCase("'none'", begin, position - begin)) | 175 if (!equalIgnoringCase("'none'", begin, position - begin)) |
207 return false; | 176 return false; |
208 | 177 |
209 skipWhile<isASCIISpace>(position, end); | 178 skipWhile<UChar, isASCIISpace>(position, end); |
210 if (position != end) | 179 if (position != end) |
211 return false; | 180 return false; |
212 | 181 |
213 return true; | 182 return true; |
214 } | 183 } |
215 | 184 |
216 class CSPSource { | 185 class CSPSource { |
217 public: | 186 public: |
218 CSPSource(ContentSecurityPolicy* policy, const String& scheme, const String&
host, int port, const String& path, bool hostHasWildcard, bool portHasWildcard) | 187 CSPSource(ContentSecurityPolicy* policy, const String& scheme, const String&
host, int port, const String& path, bool hostHasWildcard, bool portHasWildcard) |
219 : m_policy(policy) | 188 : m_policy(policy) |
(...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
362 // / *WSP "'none'" *WSP | 331 // / *WSP "'none'" *WSP |
363 // | 332 // |
364 void CSPSourceList::parse(const UChar* begin, const UChar* end) | 333 void CSPSourceList::parse(const UChar* begin, const UChar* end) |
365 { | 334 { |
366 // We represent 'none' as an empty m_list. | 335 // We represent 'none' as an empty m_list. |
367 if (isSourceListNone(begin, end)) | 336 if (isSourceListNone(begin, end)) |
368 return; | 337 return; |
369 | 338 |
370 const UChar* position = begin; | 339 const UChar* position = begin; |
371 while (position < end) { | 340 while (position < end) { |
372 skipWhile<isASCIISpace>(position, end); | 341 skipWhile<UChar, isASCIISpace>(position, end); |
373 if (position == end) | 342 if (position == end) |
374 return; | 343 return; |
375 | 344 |
376 const UChar* beginSource = position; | 345 const UChar* beginSource = position; |
377 skipWhile<isSourceCharacter>(position, end); | 346 skipWhile<UChar, isSourceCharacter>(position, end); |
378 | 347 |
379 String scheme, host, path; | 348 String scheme, host, path; |
380 int port = 0; | 349 int port = 0; |
381 bool hostHasWildcard = false; | 350 bool hostHasWildcard = false; |
382 bool portHasWildcard = false; | 351 bool portHasWildcard = false; |
383 | 352 |
384 if (parseSource(beginSource, position, scheme, host, port, path, hostHas
Wildcard, portHasWildcard)) { | 353 if (parseSource(beginSource, position, scheme, host, port, path, hostHas
Wildcard, portHasWildcard)) { |
385 // Wildcard hosts and keyword sources ('self', 'unsafe-inline', | 354 // Wildcard hosts and keyword sources ('self', 'unsafe-inline', |
386 // etc.) aren't stored in m_list, but as attributes on the source | 355 // etc.) aren't stored in m_list, but as attributes on the source |
387 // list itself. | 356 // list itself. |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
440 addSourceNonce(nonce); | 409 addSourceNonce(nonce); |
441 return true; | 410 return true; |
442 } | 411 } |
443 } | 412 } |
444 | 413 |
445 const UChar* position = begin; | 414 const UChar* position = begin; |
446 const UChar* beginHost = begin; | 415 const UChar* beginHost = begin; |
447 const UChar* beginPath = end; | 416 const UChar* beginPath = end; |
448 const UChar* beginPort = 0; | 417 const UChar* beginPort = 0; |
449 | 418 |
450 skipWhile<isNotColonOrSlash>(position, end); | 419 skipWhile<UChar, isNotColonOrSlash>(position, end); |
451 | 420 |
452 if (position == end) { | 421 if (position == end) { |
453 // host | 422 // host |
454 // ^ | 423 // ^ |
455 return parseHost(beginHost, position, host, hostHasWildcard); | 424 return parseHost(beginHost, position, host, hostHasWildcard); |
456 } | 425 } |
457 | 426 |
458 if (position < end && *position == '/') { | 427 if (position < end && *position == '/') { |
459 // host/path || host/ || / | 428 // host/path || host/ || / |
460 // ^ ^ ^ | 429 // ^ ^ ^ |
461 return parseHost(beginHost, position, host, hostHasWildcard) && parsePat
h(position, end, path); | 430 return parseHost(beginHost, position, host, hostHasWildcard) && parsePat
h(position, end, path); |
462 } | 431 } |
463 | 432 |
464 if (position < end && *position == ':') { | 433 if (position < end && *position == ':') { |
465 if (end - position == 1) { | 434 if (end - position == 1) { |
466 // scheme: | 435 // scheme: |
467 // ^ | 436 // ^ |
468 return parseScheme(begin, position, scheme); | 437 return parseScheme(begin, position, scheme); |
469 } | 438 } |
470 | 439 |
471 if (position[1] == '/') { | 440 if (position[1] == '/') { |
472 // scheme://host || scheme:// | 441 // scheme://host || scheme:// |
473 // ^ ^ | 442 // ^ ^ |
474 if (!parseScheme(begin, position, scheme) | 443 if (!parseScheme(begin, position, scheme) |
475 || !skipExactly(position, end, ':') | 444 || !skipExactly<UChar>(position, end, ':') |
476 || !skipExactly(position, end, '/') | 445 || !skipExactly<UChar>(position, end, '/') |
477 || !skipExactly(position, end, '/')) | 446 || !skipExactly<UChar>(position, end, '/')) |
478 return false; | 447 return false; |
479 if (position == end) | 448 if (position == end) |
480 return true; | 449 return true; |
481 beginHost = position; | 450 beginHost = position; |
482 skipWhile<isNotColonOrSlash>(position, end); | 451 skipWhile<UChar, isNotColonOrSlash>(position, end); |
483 } | 452 } |
484 | 453 |
485 if (position < end && *position == ':') { | 454 if (position < end && *position == ':') { |
486 // host:port || scheme://host:port | 455 // host:port || scheme://host:port |
487 // ^ ^ | 456 // ^ ^ |
488 beginPort = position; | 457 beginPort = position; |
489 skipUntil(position, end, '/'); | 458 skipUntil<UChar>(position, end, '/'); |
490 } | 459 } |
491 } | 460 } |
492 | 461 |
493 if (position < end && *position == '/') { | 462 if (position < end && *position == '/') { |
494 // scheme://host/path || scheme://host:port/path | 463 // scheme://host/path || scheme://host:port/path |
495 // ^ ^ | 464 // ^ ^ |
496 if (position == beginHost) | 465 if (position == beginHost) |
497 return false; | 466 return false; |
498 beginPath = position; | 467 beginPath = position; |
499 } | 468 } |
(...skipping 22 matching lines...) Expand all Loading... |
522 bool CSPSourceList::parseNonce(const UChar* begin, const UChar* end, String& non
ce) | 491 bool CSPSourceList::parseNonce(const UChar* begin, const UChar* end, String& non
ce) |
523 { | 492 { |
524 DEFINE_STATIC_LOCAL(const String, noncePrefix, ("'nonce-")); | 493 DEFINE_STATIC_LOCAL(const String, noncePrefix, ("'nonce-")); |
525 | 494 |
526 if (!equalIgnoringCase(noncePrefix.characters8(), begin, noncePrefix.length(
))) | 495 if (!equalIgnoringCase(noncePrefix.characters8(), begin, noncePrefix.length(
))) |
527 return true; | 496 return true; |
528 | 497 |
529 const UChar* position = begin + noncePrefix.length(); | 498 const UChar* position = begin + noncePrefix.length(); |
530 const UChar* nonceBegin = position; | 499 const UChar* nonceBegin = position; |
531 | 500 |
532 skipWhile<isNonceCharacter>(position, end); | 501 skipWhile<UChar, isNonceCharacter>(position, end); |
533 ASSERT(nonceBegin <= position); | 502 ASSERT(nonceBegin <= position); |
534 | 503 |
535 if (((position + 1) != end && *position != '\'') || !(position - nonceBegin
)) | 504 if (((position + 1) != end && *position != '\'') || !(position - nonceBegin
)) |
536 return false; | 505 return false; |
537 | 506 |
538 nonce = String(nonceBegin, position - nonceBegin); | 507 nonce = String(nonceBegin, position - nonceBegin); |
539 return true; | 508 return true; |
540 } | 509 } |
541 | 510 |
542 // ; <scheme> production from RFC 3986 | 511 // ; <scheme> production from RFC 3986 |
543 // scheme = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." ) | 512 // scheme = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." ) |
544 // | 513 // |
545 bool CSPSourceList::parseScheme(const UChar* begin, const UChar* end, String& sc
heme) | 514 bool CSPSourceList::parseScheme(const UChar* begin, const UChar* end, String& sc
heme) |
546 { | 515 { |
547 ASSERT(begin <= end); | 516 ASSERT(begin <= end); |
548 ASSERT(scheme.isEmpty()); | 517 ASSERT(scheme.isEmpty()); |
549 | 518 |
550 if (begin == end) | 519 if (begin == end) |
551 return false; | 520 return false; |
552 | 521 |
553 const UChar* position = begin; | 522 const UChar* position = begin; |
554 | 523 |
555 if (!skipExactly<isASCIIAlpha>(position, end)) | 524 if (!skipExactly<UChar, isASCIIAlpha>(position, end)) |
556 return false; | 525 return false; |
557 | 526 |
558 skipWhile<isSchemeContinuationCharacter>(position, end); | 527 skipWhile<UChar, isSchemeContinuationCharacter>(position, end); |
559 | 528 |
560 if (position != end) | 529 if (position != end) |
561 return false; | 530 return false; |
562 | 531 |
563 scheme = String(begin, end - begin); | 532 scheme = String(begin, end - begin); |
564 return true; | 533 return true; |
565 } | 534 } |
566 | 535 |
567 // host = [ "*." ] 1*host-char *( "." 1*host-char ) | 536 // host = [ "*." ] 1*host-char *( "." 1*host-char ) |
568 // / "*" | 537 // / "*" |
569 // host-char = ALPHA / DIGIT / "-" | 538 // host-char = ALPHA / DIGIT / "-" |
570 // | 539 // |
571 bool CSPSourceList::parseHost(const UChar* begin, const UChar* end, String& host
, bool& hostHasWildcard) | 540 bool CSPSourceList::parseHost(const UChar* begin, const UChar* end, String& host
, bool& hostHasWildcard) |
572 { | 541 { |
573 ASSERT(begin <= end); | 542 ASSERT(begin <= end); |
574 ASSERT(host.isEmpty()); | 543 ASSERT(host.isEmpty()); |
575 ASSERT(!hostHasWildcard); | 544 ASSERT(!hostHasWildcard); |
576 | 545 |
577 if (begin == end) | 546 if (begin == end) |
578 return false; | 547 return false; |
579 | 548 |
580 const UChar* position = begin; | 549 const UChar* position = begin; |
581 | 550 |
582 if (skipExactly(position, end, '*')) { | 551 if (skipExactly<UChar>(position, end, '*')) { |
583 hostHasWildcard = true; | 552 hostHasWildcard = true; |
584 | 553 |
585 if (position == end) | 554 if (position == end) |
586 return true; | 555 return true; |
587 | 556 |
588 if (!skipExactly(position, end, '.')) | 557 if (!skipExactly<UChar>(position, end, '.')) |
589 return false; | 558 return false; |
590 } | 559 } |
591 | 560 |
592 const UChar* hostBegin = position; | 561 const UChar* hostBegin = position; |
593 | 562 |
594 while (position < end) { | 563 while (position < end) { |
595 if (!skipExactly<isHostCharacter>(position, end)) | 564 if (!skipExactly<UChar, isHostCharacter>(position, end)) |
596 return false; | 565 return false; |
597 | 566 |
598 skipWhile<isHostCharacter>(position, end); | 567 skipWhile<UChar, isHostCharacter>(position, end); |
599 | 568 |
600 if (position < end && !skipExactly(position, end, '.')) | 569 if (position < end && !skipExactly<UChar>(position, end, '.')) |
601 return false; | 570 return false; |
602 } | 571 } |
603 | 572 |
604 ASSERT(position == end); | 573 ASSERT(position == end); |
605 host = String(hostBegin, end - hostBegin); | 574 host = String(hostBegin, end - hostBegin); |
606 return true; | 575 return true; |
607 } | 576 } |
608 | 577 |
609 bool CSPSourceList::parsePath(const UChar* begin, const UChar* end, String& path
) | 578 bool CSPSourceList::parsePath(const UChar* begin, const UChar* end, String& path
) |
610 { | 579 { |
611 ASSERT(begin <= end); | 580 ASSERT(begin <= end); |
612 ASSERT(path.isEmpty()); | 581 ASSERT(path.isEmpty()); |
613 | 582 |
614 const UChar* position = begin; | 583 const UChar* position = begin; |
615 skipWhile<isPathComponentCharacter>(position, end); | 584 skipWhile<UChar, isPathComponentCharacter>(position, end); |
616 // path/to/file.js?query=string || path/to/file.js#anchor | 585 // path/to/file.js?query=string || path/to/file.js#anchor |
617 // ^ ^ | 586 // ^ ^ |
618 if (position < end) | 587 if (position < end) |
619 m_policy->reportInvalidPathCharacter(m_directiveName, String(begin, end
- begin), *position); | 588 m_policy->reportInvalidPathCharacter(m_directiveName, String(begin, end
- begin), *position); |
620 | 589 |
621 path = decodeURLEscapeSequences(String(begin, position - begin)); | 590 path = decodeURLEscapeSequences(String(begin, position - begin)); |
622 | 591 |
623 ASSERT(position <= end); | 592 ASSERT(position <= end); |
624 ASSERT(position == end || (*position == '#' || *position == '?')); | 593 ASSERT(position == end || (*position == '#' || *position == '?')); |
625 return true; | 594 return true; |
626 } | 595 } |
627 | 596 |
628 // port = ":" ( 1*DIGIT / "*" ) | 597 // port = ":" ( 1*DIGIT / "*" ) |
629 // | 598 // |
630 bool CSPSourceList::parsePort(const UChar* begin, const UChar* end, int& port, b
ool& portHasWildcard) | 599 bool CSPSourceList::parsePort(const UChar* begin, const UChar* end, int& port, b
ool& portHasWildcard) |
631 { | 600 { |
632 ASSERT(begin <= end); | 601 ASSERT(begin <= end); |
633 ASSERT(!port); | 602 ASSERT(!port); |
634 ASSERT(!portHasWildcard); | 603 ASSERT(!portHasWildcard); |
635 | 604 |
636 if (!skipExactly(begin, end, ':')) | 605 if (!skipExactly<UChar>(begin, end, ':')) |
637 ASSERT_NOT_REACHED(); | 606 ASSERT_NOT_REACHED(); |
638 | 607 |
639 if (begin == end) | 608 if (begin == end) |
640 return false; | 609 return false; |
641 | 610 |
642 if (end - begin == 1 && *begin == '*') { | 611 if (end - begin == 1 && *begin == '*') { |
643 port = 0; | 612 port = 0; |
644 portHasWildcard = true; | 613 portHasWildcard = true; |
645 return true; | 614 return true; |
646 } | 615 } |
647 | 616 |
648 const UChar* position = begin; | 617 const UChar* position = begin; |
649 skipWhile<isASCIIDigit>(position, end); | 618 skipWhile<UChar, isASCIIDigit>(position, end); |
650 | 619 |
651 if (position != end) | 620 if (position != end) |
652 return false; | 621 return false; |
653 | 622 |
654 bool ok; | 623 bool ok; |
655 port = charactersToIntStrict(begin, end - begin, &ok); | 624 port = charactersToIntStrict(begin, end - begin, &ok); |
656 return ok; | 625 return ok; |
657 } | 626 } |
658 | 627 |
659 void CSPSourceList::addSourceSelf() | 628 void CSPSourceList::addSourceSelf() |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
723 | 692 |
724 // 'plugin-types ____;' OR 'plugin-types;' | 693 // 'plugin-types ____;' OR 'plugin-types;' |
725 if (position == end) { | 694 if (position == end) { |
726 policy()->reportInvalidPluginTypes(String()); | 695 policy()->reportInvalidPluginTypes(String()); |
727 return; | 696 return; |
728 } | 697 } |
729 | 698 |
730 while (position < end) { | 699 while (position < end) { |
731 // _____ OR _____mime1/mime1 | 700 // _____ OR _____mime1/mime1 |
732 // ^ ^ | 701 // ^ ^ |
733 skipWhile<isASCIISpace>(position, end); | 702 skipWhile<UChar, isASCIISpace>(position, end); |
734 if (position == end) | 703 if (position == end) |
735 return; | 704 return; |
736 | 705 |
737 // mime1/mime1 mime2/mime2 | 706 // mime1/mime1 mime2/mime2 |
738 // ^ | 707 // ^ |
739 begin = position; | 708 begin = position; |
740 if (!skipExactly<isMediaTypeCharacter>(position, end)) { | 709 if (!skipExactly<UChar, isMediaTypeCharacter>(position, end)) { |
741 skipWhile<isNotASCIISpace>(position, end); | 710 skipWhile<UChar, isNotASCIISpace>(position, end); |
742 policy()->reportInvalidPluginTypes(String(begin, position - begi
n)); | 711 policy()->reportInvalidPluginTypes(String(begin, position - begi
n)); |
743 continue; | 712 continue; |
744 } | 713 } |
745 skipWhile<isMediaTypeCharacter>(position, end); | 714 skipWhile<UChar, isMediaTypeCharacter>(position, end); |
746 | 715 |
747 // mime1/mime1 mime2/mime2 | 716 // mime1/mime1 mime2/mime2 |
748 // ^ | 717 // ^ |
749 if (!skipExactly(position, end, '/')) { | 718 if (!skipExactly<UChar>(position, end, '/')) { |
750 skipWhile<isNotASCIISpace>(position, end); | 719 skipWhile<UChar, isNotASCIISpace>(position, end); |
751 policy()->reportInvalidPluginTypes(String(begin, position - begi
n)); | 720 policy()->reportInvalidPluginTypes(String(begin, position - begi
n)); |
752 continue; | 721 continue; |
753 } | 722 } |
754 | 723 |
755 // mime1/mime1 mime2/mime2 | 724 // mime1/mime1 mime2/mime2 |
756 // ^ | 725 // ^ |
757 if (!skipExactly<isMediaTypeCharacter>(position, end)) { | 726 if (!skipExactly<UChar, isMediaTypeCharacter>(position, end)) { |
758 skipWhile<isNotASCIISpace>(position, end); | 727 skipWhile<UChar, isNotASCIISpace>(position, end); |
759 policy()->reportInvalidPluginTypes(String(begin, position - begi
n)); | 728 policy()->reportInvalidPluginTypes(String(begin, position - begi
n)); |
760 continue; | 729 continue; |
761 } | 730 } |
762 skipWhile<isMediaTypeCharacter>(position, end); | 731 skipWhile<UChar, isMediaTypeCharacter>(position, end); |
763 | 732 |
764 // mime1/mime1 mime2/mime2 OR mime1/mime1 OR mime1/mime1/error | 733 // mime1/mime1 mime2/mime2 OR mime1/mime1 OR mime1/mime1/error |
765 // ^ ^ ^ | 734 // ^ ^ ^ |
766 if (position < end && isNotASCIISpace(*position)) { | 735 if (position < end && isNotASCIISpace(*position)) { |
767 skipWhile<isNotASCIISpace>(position, end); | 736 skipWhile<UChar, isNotASCIISpace>(position, end); |
768 policy()->reportInvalidPluginTypes(String(begin, position - begi
n)); | 737 policy()->reportInvalidPluginTypes(String(begin, position - begi
n)); |
769 continue; | 738 continue; |
770 } | 739 } |
771 m_pluginTypes.add(String(begin, position - begin)); | 740 m_pluginTypes.add(String(begin, position - begin)); |
772 | 741 |
773 ASSERT(position == end || isASCIISpace(*position)); | 742 ASSERT(position == end || isASCIISpace(*position)); |
774 } | 743 } |
775 } | 744 } |
776 | 745 |
777 HashSet<String> m_pluginTypes; | 746 HashSet<String> m_pluginTypes; |
(...skipping 428 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1206 void CSPDirectiveList::parse(const UChar* begin, const UChar* end) | 1175 void CSPDirectiveList::parse(const UChar* begin, const UChar* end) |
1207 { | 1176 { |
1208 m_header = String(begin, end - begin); | 1177 m_header = String(begin, end - begin); |
1209 | 1178 |
1210 if (begin == end) | 1179 if (begin == end) |
1211 return; | 1180 return; |
1212 | 1181 |
1213 const UChar* position = begin; | 1182 const UChar* position = begin; |
1214 while (position < end) { | 1183 while (position < end) { |
1215 const UChar* directiveBegin = position; | 1184 const UChar* directiveBegin = position; |
1216 skipUntil(position, end, ';'); | 1185 skipUntil<UChar>(position, end, ';'); |
1217 | 1186 |
1218 String name, value; | 1187 String name, value; |
1219 if (parseDirective(directiveBegin, position, name, value)) { | 1188 if (parseDirective(directiveBegin, position, name, value)) { |
1220 ASSERT(!name.isEmpty()); | 1189 ASSERT(!name.isEmpty()); |
1221 addDirective(name, value); | 1190 addDirective(name, value); |
1222 } | 1191 } |
1223 | 1192 |
1224 ASSERT(position == end || *position == ';'); | 1193 ASSERT(position == end || *position == ';'); |
1225 skipExactly(position, end, ';'); | 1194 skipExactly<UChar>(position, end, ';'); |
1226 } | 1195 } |
1227 } | 1196 } |
1228 | 1197 |
1229 // directive = *WSP [ directive-name [ WSP directive-value ] ] | 1198 // directive = *WSP [ directive-name [ WSP directive-value ] ] |
1230 // directive-name = 1*( ALPHA / DIGIT / "-" ) | 1199 // directive-name = 1*( ALPHA / DIGIT / "-" ) |
1231 // directive-value = *( WSP / <VCHAR except ";"> ) | 1200 // directive-value = *( WSP / <VCHAR except ";"> ) |
1232 // | 1201 // |
1233 bool CSPDirectiveList::parseDirective(const UChar* begin, const UChar* end, Stri
ng& name, String& value) | 1202 bool CSPDirectiveList::parseDirective(const UChar* begin, const UChar* end, Stri
ng& name, String& value) |
1234 { | 1203 { |
1235 ASSERT(name.isEmpty()); | 1204 ASSERT(name.isEmpty()); |
1236 ASSERT(value.isEmpty()); | 1205 ASSERT(value.isEmpty()); |
1237 | 1206 |
1238 const UChar* position = begin; | 1207 const UChar* position = begin; |
1239 skipWhile<isASCIISpace>(position, end); | 1208 skipWhile<UChar, isASCIISpace>(position, end); |
1240 | 1209 |
1241 // Empty directive (e.g. ";;;"). Exit early. | 1210 // Empty directive (e.g. ";;;"). Exit early. |
1242 if (position == end) | 1211 if (position == end) |
1243 return false; | 1212 return false; |
1244 | 1213 |
1245 const UChar* nameBegin = position; | 1214 const UChar* nameBegin = position; |
1246 skipWhile<isDirectiveNameCharacter>(position, end); | 1215 skipWhile<UChar, isDirectiveNameCharacter>(position, end); |
1247 | 1216 |
1248 // The directive-name must be non-empty. | 1217 // The directive-name must be non-empty. |
1249 if (nameBegin == position) { | 1218 if (nameBegin == position) { |
1250 skipWhile<isNotASCIISpace>(position, end); | 1219 skipWhile<UChar, isNotASCIISpace>(position, end); |
1251 m_policy->reportUnsupportedDirective(String(nameBegin, position - nameBe
gin)); | 1220 m_policy->reportUnsupportedDirective(String(nameBegin, position - nameBe
gin)); |
1252 return false; | 1221 return false; |
1253 } | 1222 } |
1254 | 1223 |
1255 name = String(nameBegin, position - nameBegin); | 1224 name = String(nameBegin, position - nameBegin); |
1256 | 1225 |
1257 if (position == end) | 1226 if (position == end) |
1258 return true; | 1227 return true; |
1259 | 1228 |
1260 if (!skipExactly<isASCIISpace>(position, end)) { | 1229 if (!skipExactly<UChar, isASCIISpace>(position, end)) { |
1261 skipWhile<isNotASCIISpace>(position, end); | 1230 skipWhile<UChar, isNotASCIISpace>(position, end); |
1262 m_policy->reportUnsupportedDirective(String(nameBegin, position - nameBe
gin)); | 1231 m_policy->reportUnsupportedDirective(String(nameBegin, position - nameBe
gin)); |
1263 return false; | 1232 return false; |
1264 } | 1233 } |
1265 | 1234 |
1266 skipWhile<isASCIISpace>(position, end); | 1235 skipWhile<UChar, isASCIISpace>(position, end); |
1267 | 1236 |
1268 const UChar* valueBegin = position; | 1237 const UChar* valueBegin = position; |
1269 skipWhile<isDirectiveValueCharacter>(position, end); | 1238 skipWhile<UChar, isDirectiveValueCharacter>(position, end); |
1270 | 1239 |
1271 if (position != end) { | 1240 if (position != end) { |
1272 m_policy->reportInvalidDirectiveValueCharacter(name, String(valueBegin,
end - valueBegin)); | 1241 m_policy->reportInvalidDirectiveValueCharacter(name, String(valueBegin,
end - valueBegin)); |
1273 return false; | 1242 return false; |
1274 } | 1243 } |
1275 | 1244 |
1276 // The directive-value may be empty. | 1245 // The directive-value may be empty. |
1277 if (valueBegin == position) | 1246 if (valueBegin == position) |
1278 return true; | 1247 return true; |
1279 | 1248 |
1280 value = String(valueBegin, position - valueBegin); | 1249 value = String(valueBegin, position - valueBegin); |
1281 return true; | 1250 return true; |
1282 } | 1251 } |
1283 | 1252 |
1284 void CSPDirectiveList::parseReportURI(const String& name, const String& value) | 1253 void CSPDirectiveList::parseReportURI(const String& name, const String& value) |
1285 { | 1254 { |
1286 if (!m_reportURIs.isEmpty()) { | 1255 if (!m_reportURIs.isEmpty()) { |
1287 m_policy->reportDuplicateDirective(name); | 1256 m_policy->reportDuplicateDirective(name); |
1288 return; | 1257 return; |
1289 } | 1258 } |
1290 | 1259 |
1291 Vector<UChar> characters; | 1260 Vector<UChar> characters; |
1292 value.appendTo(characters); | 1261 value.appendTo(characters); |
1293 | 1262 |
1294 const UChar* position = characters.data(); | 1263 const UChar* position = characters.data(); |
1295 const UChar* end = position + characters.size(); | 1264 const UChar* end = position + characters.size(); |
1296 | 1265 |
1297 while (position < end) { | 1266 while (position < end) { |
1298 skipWhile<isASCIISpace>(position, end); | 1267 skipWhile<UChar, isASCIISpace>(position, end); |
1299 | 1268 |
1300 const UChar* urlBegin = position; | 1269 const UChar* urlBegin = position; |
1301 skipWhile<isNotASCIISpace>(position, end); | 1270 skipWhile<UChar, isNotASCIISpace>(position, end); |
1302 | 1271 |
1303 if (urlBegin < position) { | 1272 if (urlBegin < position) { |
1304 String url = String(urlBegin, position - urlBegin); | 1273 String url = String(urlBegin, position - urlBegin); |
1305 m_reportURIs.append(m_policy->completeURL(url)); | 1274 m_reportURIs.append(m_policy->completeURL(url)); |
1306 } | 1275 } |
1307 } | 1276 } |
1308 } | 1277 } |
1309 | 1278 |
1310 | 1279 |
1311 template<class CSPDirectiveType> | 1280 template<class CSPDirectiveType> |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1344 m_policy->reportInvalidReflectedXSS(value); | 1313 m_policy->reportInvalidReflectedXSS(value); |
1345 return; | 1314 return; |
1346 } | 1315 } |
1347 | 1316 |
1348 Vector<UChar> characters; | 1317 Vector<UChar> characters; |
1349 value.appendTo(characters); | 1318 value.appendTo(characters); |
1350 | 1319 |
1351 const UChar* position = characters.data(); | 1320 const UChar* position = characters.data(); |
1352 const UChar* end = position + characters.size(); | 1321 const UChar* end = position + characters.size(); |
1353 | 1322 |
1354 skipWhile<isASCIISpace>(position, end); | 1323 skipWhile<UChar, isASCIISpace>(position, end); |
1355 const UChar* begin = position; | 1324 const UChar* begin = position; |
1356 skipWhile<isNotASCIISpace>(position, end); | 1325 skipWhile<UChar, isNotASCIISpace>(position, end); |
1357 | 1326 |
1358 // value1 | 1327 // value1 |
1359 // ^ | 1328 // ^ |
1360 if (equalIgnoringCase("allow", begin, position - begin)) | 1329 if (equalIgnoringCase("allow", begin, position - begin)) |
1361 m_reflectedXSSDisposition = ContentSecurityPolicy::AllowReflectedXSS; | 1330 m_reflectedXSSDisposition = ContentSecurityPolicy::AllowReflectedXSS; |
1362 else if (equalIgnoringCase("filter", begin, position - begin)) | 1331 else if (equalIgnoringCase("filter", begin, position - begin)) |
1363 m_reflectedXSSDisposition = ContentSecurityPolicy::FilterReflectedXSS; | 1332 m_reflectedXSSDisposition = ContentSecurityPolicy::FilterReflectedXSS; |
1364 else if (equalIgnoringCase("block", begin, position - begin)) | 1333 else if (equalIgnoringCase("block", begin, position - begin)) |
1365 m_reflectedXSSDisposition = ContentSecurityPolicy::BlockReflectedXSS; | 1334 m_reflectedXSSDisposition = ContentSecurityPolicy::BlockReflectedXSS; |
1366 else { | 1335 else { |
1367 m_reflectedXSSDisposition = ContentSecurityPolicy::ReflectedXSSInvalid; | 1336 m_reflectedXSSDisposition = ContentSecurityPolicy::ReflectedXSSInvalid; |
1368 m_policy->reportInvalidReflectedXSS(value); | 1337 m_policy->reportInvalidReflectedXSS(value); |
1369 return; | 1338 return; |
1370 } | 1339 } |
1371 | 1340 |
1372 skipWhile<isASCIISpace>(position, end); | 1341 skipWhile<UChar, isASCIISpace>(position, end); |
1373 if (position == end && m_reflectedXSSDisposition != ContentSecurityPolicy::R
eflectedXSSUnset) | 1342 if (position == end && m_reflectedXSSDisposition != ContentSecurityPolicy::R
eflectedXSSUnset) |
1374 return; | 1343 return; |
1375 | 1344 |
1376 // value1 value2 | 1345 // value1 value2 |
1377 // ^ | 1346 // ^ |
1378 m_reflectedXSSDisposition = ContentSecurityPolicy::ReflectedXSSInvalid; | 1347 m_reflectedXSSDisposition = ContentSecurityPolicy::ReflectedXSSInvalid; |
1379 m_policy->reportInvalidReflectedXSS(value); | 1348 m_policy->reportInvalidReflectedXSS(value); |
1380 } | 1349 } |
1381 | 1350 |
1382 void CSPDirectiveList::addDirective(const String& name, const String& value) | 1351 void CSPDirectiveList::addDirective(const String& name, const String& value) |
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1469 header.appendTo(characters); | 1438 header.appendTo(characters); |
1470 | 1439 |
1471 const UChar* begin = characters.data(); | 1440 const UChar* begin = characters.data(); |
1472 const UChar* end = begin + characters.size(); | 1441 const UChar* end = begin + characters.size(); |
1473 | 1442 |
1474 // RFC2616, section 4.2 specifies that headers appearing multiple times can | 1443 // RFC2616, section 4.2 specifies that headers appearing multiple times can |
1475 // be combined with a comma. Walk the header string, and parse each comma | 1444 // be combined with a comma. Walk the header string, and parse each comma |
1476 // separated chunk as a separate header. | 1445 // separated chunk as a separate header. |
1477 const UChar* position = begin; | 1446 const UChar* position = begin; |
1478 while (position < end) { | 1447 while (position < end) { |
1479 skipUntil(position, end, ','); | 1448 skipUntil<UChar>(position, end, ','); |
1480 | 1449 |
1481 // header1,header2 OR header1 | 1450 // header1,header2 OR header1 |
1482 // ^ ^ | 1451 // ^ ^ |
1483 OwnPtr<CSPDirectiveList> policy = CSPDirectiveList::create(this, begin,
position, type); | 1452 OwnPtr<CSPDirectiveList> policy = CSPDirectiveList::create(this, begin,
position, type); |
1484 | 1453 |
1485 // We disable 'eval()' even in the case of report-only policies, and rel
y on the check in the V8Initializer::codeGenerationCheckCallbackInMainThread cal
lback to determine whether the call should execute or not. | 1454 // We disable 'eval()' even in the case of report-only policies, and rel
y on the check in the V8Initializer::codeGenerationCheckCallbackInMainThread cal
lback to determine whether the call should execute or not. |
1486 if (!policy->allowEval(0, SuppressReport)) | 1455 if (!policy->allowEval(0, SuppressReport)) |
1487 m_scriptExecutionContext->disableEval(policy->evalDisabledErrorMessa
ge()); | 1456 m_scriptExecutionContext->disableEval(policy->evalDisabledErrorMessa
ge()); |
1488 | 1457 |
1489 m_policies.append(policy.release()); | 1458 m_policies.append(policy.release()); |
1490 | 1459 |
1491 // Skip the comma, and begin the next header from the current position. | 1460 // Skip the comma, and begin the next header from the current position. |
1492 ASSERT(position == end || *position == ','); | 1461 ASSERT(position == end || *position == ','); |
1493 skipExactly(position, end, ','); | 1462 skipExactly<UChar>(position, end, ','); |
1494 begin = position; | 1463 begin = position; |
1495 } | 1464 } |
1496 } | 1465 } |
1497 | 1466 |
1498 void ContentSecurityPolicy::setOverrideAllowInlineStyle(bool value) | 1467 void ContentSecurityPolicy::setOverrideAllowInlineStyle(bool value) |
1499 { | 1468 { |
1500 m_overrideInlineStyleAllowed = value; | 1469 m_overrideInlineStyleAllowed = value; |
1501 } | 1470 } |
1502 | 1471 |
1503 const String& ContentSecurityPolicy::deprecatedHeader() const | 1472 const String& ContentSecurityPolicy::deprecatedHeader() const |
(...skipping 416 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1920 // Collisions have no security impact, so we can save space by storing only
the string's hash rather than the whole report. | 1889 // Collisions have no security impact, so we can save space by storing only
the string's hash rather than the whole report. |
1921 return !m_violationReportsSent.contains(report.impl()->hash()); | 1890 return !m_violationReportsSent.contains(report.impl()->hash()); |
1922 } | 1891 } |
1923 | 1892 |
1924 void ContentSecurityPolicy::didSendViolationReport(const String& report) | 1893 void ContentSecurityPolicy::didSendViolationReport(const String& report) |
1925 { | 1894 { |
1926 m_violationReportsSent.add(report.impl()->hash()); | 1895 m_violationReportsSent.add(report.impl()->hash()); |
1927 } | 1896 } |
1928 | 1897 |
1929 } // namespace WebCore | 1898 } // namespace WebCore |
OLD | NEW |