OLD | NEW |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 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 #include "content/renderer/render_frame_impl.h" | 5 #include "content/renderer/render_frame_impl.h" |
6 | 6 |
7 #include <map> | 7 #include <map> |
8 #include <string> | 8 #include <string> |
9 #include <utility> | 9 #include <utility> |
10 #include <vector> | 10 #include <vector> |
(...skipping 413 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
424 } | 424 } |
425 | 425 |
426 bool IsBrowserInitiated(NavigationParams* pending) { | 426 bool IsBrowserInitiated(NavigationParams* pending) { |
427 // A navigation resulting from loading a javascript URL should not be treated | 427 // A navigation resulting from loading a javascript URL should not be treated |
428 // as a browser initiated event. Instead, we want it to look as if the page | 428 // as a browser initiated event. Instead, we want it to look as if the page |
429 // initiated any load resulting from JS execution. | 429 // initiated any load resulting from JS execution. |
430 return pending && | 430 return pending && |
431 !pending->common_params.url.SchemeIs(url::kJavaScriptScheme); | 431 !pending->common_params.url.SchemeIs(url::kJavaScriptScheme); |
432 } | 432 } |
433 | 433 |
434 NOINLINE void ExhaustMemory() { | |
435 volatile void* ptr = nullptr; | |
436 do { | |
437 ptr = malloc(0x10000000); | |
438 base::debug::Alias(&ptr); | |
439 } while (ptr); | |
440 } | |
441 | |
442 NOINLINE void CrashIntentionally() { | |
443 // NOTE(shess): Crash directly rather than using NOTREACHED() so | |
444 // that the signature is easier to triage in crash reports. | |
445 // | |
446 // Linker's ICF feature may merge this function with other functions with the | |
447 // same definition and it may confuse the crash report processing system. | |
448 static int static_variable_to_make_this_function_unique = 0; | |
449 base::debug::Alias(&static_variable_to_make_this_function_unique); | |
450 | |
451 volatile int* zero = nullptr; | |
452 *zero = 0; | |
453 } | |
454 | |
455 NOINLINE void BadCastCrashIntentionally() { | |
456 class A { | |
457 virtual void f() {} | |
458 }; | |
459 | |
460 class B { | |
461 virtual void f() {} | |
462 }; | |
463 | |
464 A a; | |
465 (void)(B*)&a; | |
466 } | |
467 | |
468 #if defined(ADDRESS_SANITIZER) || defined(SYZYASAN) | |
469 NOINLINE void MaybeTriggerAsanError(const GURL& url) { | |
470 // NOTE(rogerm): We intentionally perform an invalid heap access here in | |
471 // order to trigger an Address Sanitizer (ASAN) error report. | |
472 const char kCrashDomain[] = "crash"; | |
473 const char kHeapOverflow[] = "/heap-overflow"; | |
474 const char kHeapUnderflow[] = "/heap-underflow"; | |
475 const char kUseAfterFree[] = "/use-after-free"; | |
476 #if defined(SYZYASAN) | |
477 const char kCorruptHeapBlock[] = "/corrupt-heap-block"; | |
478 const char kCorruptHeap[] = "/corrupt-heap"; | |
479 #endif | |
480 | |
481 if (!url.DomainIs(kCrashDomain)) | |
482 return; | |
483 | |
484 if (!url.has_path()) | |
485 return; | |
486 | |
487 std::string crash_type(url.path()); | |
488 if (crash_type == kHeapOverflow) { | |
489 LOG(ERROR) | |
490 << "Intentionally causing ASAN heap overflow" | |
491 << " because user navigated to " << url.spec(); | |
492 base::debug::AsanHeapOverflow(); | |
493 } else if (crash_type == kHeapUnderflow) { | |
494 LOG(ERROR) | |
495 << "Intentionally causing ASAN heap underflow" | |
496 << " because user navigated to " << url.spec(); | |
497 base::debug::AsanHeapUnderflow(); | |
498 } else if (crash_type == kUseAfterFree) { | |
499 LOG(ERROR) | |
500 << "Intentionally causing ASAN heap use-after-free" | |
501 << " because user navigated to " << url.spec(); | |
502 base::debug::AsanHeapUseAfterFree(); | |
503 #if defined(SYZYASAN) | |
504 } else if (crash_type == kCorruptHeapBlock) { | |
505 LOG(ERROR) | |
506 << "Intentionally causing ASAN corrupt heap block" | |
507 << " because user navigated to " << url.spec(); | |
508 base::debug::AsanCorruptHeapBlock(); | |
509 } else if (crash_type == kCorruptHeap) { | |
510 LOG(ERROR) | |
511 << "Intentionally causing ASAN corrupt heap" | |
512 << " because user navigated to " << url.spec(); | |
513 base::debug::AsanCorruptHeap(); | |
514 #endif | |
515 } | |
516 } | |
517 #endif // ADDRESS_SANITIZER || SYZYASAN | |
518 | |
519 void MaybeHandleDebugURL(const GURL& url) { | |
520 if (!url.SchemeIs(kChromeUIScheme)) | |
521 return; | |
522 if (url == kChromeUIBadCastCrashURL) { | |
523 LOG(ERROR) | |
524 << "Intentionally crashing (with bad cast)" | |
525 << " because user navigated to " << url.spec(); | |
526 BadCastCrashIntentionally(); | |
527 } else if (url == kChromeUICrashURL) { | |
528 LOG(ERROR) << "Intentionally crashing (with null pointer dereference)" | |
529 << " because user navigated to " << url.spec(); | |
530 CrashIntentionally(); | |
531 } else if (url == kChromeUIDumpURL) { | |
532 // This URL will only correctly create a crash dump file if content is | |
533 // hosted in a process that has correctly called | |
534 // base::debug::SetDumpWithoutCrashingFunction. Refer to the documentation | |
535 // of base::debug::DumpWithoutCrashing for more details. | |
536 base::debug::DumpWithoutCrashing(); | |
537 } else if (url == kChromeUIKillURL) { | |
538 LOG(ERROR) << "Intentionally issuing kill signal to current process" | |
539 << " because user navigated to " << url.spec(); | |
540 base::Process::Current().Terminate(1, false); | |
541 } else if (url == kChromeUIHangURL) { | |
542 LOG(ERROR) << "Intentionally hanging ourselves with sleep infinite loop" | |
543 << " because user navigated to " << url.spec(); | |
544 for (;;) { | |
545 base::PlatformThread::Sleep(base::TimeDelta::FromSeconds(1)); | |
546 } | |
547 } else if (url == kChromeUIShorthangURL) { | |
548 LOG(ERROR) << "Intentionally sleeping renderer for 20 seconds" | |
549 << " because user navigated to " << url.spec(); | |
550 base::PlatformThread::Sleep(base::TimeDelta::FromSeconds(20)); | |
551 } else if (url == kChromeUIMemoryExhaustURL) { | |
552 LOG(ERROR) | |
553 << "Intentionally exhausting renderer memory because user navigated to " | |
554 << url.spec(); | |
555 ExhaustMemory(); | |
556 } else if (url == kChromeUICheckCrashURL) { | |
557 LOG(ERROR) | |
558 << "Intentionally causing CHECK because user navigated to " | |
559 << url.spec(); | |
560 CHECK(false); | |
561 } | |
562 | |
563 #if defined(ADDRESS_SANITIZER) || defined(SYZYASAN) | |
564 MaybeTriggerAsanError(url); | |
565 #endif // ADDRESS_SANITIZER || SYZYASAN | |
566 } | |
567 | |
568 // Returns false unless this is a top-level navigation. | 434 // Returns false unless this is a top-level navigation. |
569 bool IsTopLevelNavigation(WebFrame* frame) { | 435 bool IsTopLevelNavigation(WebFrame* frame) { |
570 return frame->parent() == NULL; | 436 return frame->parent() == NULL; |
571 } | 437 } |
572 | 438 |
573 WebURLRequest CreateURLRequestForNavigation( | 439 WebURLRequest CreateURLRequestForNavigation( |
574 const CommonNavigationParams& common_params, | 440 const CommonNavigationParams& common_params, |
575 const RequestNavigationParams& request_params, | 441 const RequestNavigationParams& request_params, |
576 std::unique_ptr<StreamOverrideParameters> stream_override, | 442 std::unique_ptr<StreamOverrideParameters> stream_override, |
577 bool is_view_source_mode_enabled, | 443 bool is_view_source_mode_enabled, |
(...skipping 317 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
895 return false; | 761 return false; |
896 } | 762 } |
897 #endif // defined(OS_ANDROID) | 763 #endif // defined(OS_ANDROID) |
898 | 764 |
899 double ConvertToBlinkTime(const base::TimeTicks& time_ticks) { | 765 double ConvertToBlinkTime(const base::TimeTicks& time_ticks) { |
900 return (time_ticks - base::TimeTicks()).InSecondsF(); | 766 return (time_ticks - base::TimeTicks()).InSecondsF(); |
901 } | 767 } |
902 | 768 |
903 } // namespace | 769 } // namespace |
904 | 770 |
| 771 // The following methods are outside of the anonymous namespace to ensure that |
| 772 // the corresponding symbols get emmitted even on symbol_level 1. |
| 773 NOINLINE void ExhaustMemory() { |
| 774 volatile void* ptr = nullptr; |
| 775 do { |
| 776 ptr = malloc(0x10000000); |
| 777 base::debug::Alias(&ptr); |
| 778 } while (ptr); |
| 779 } |
| 780 |
| 781 NOINLINE void CrashIntentionally() { |
| 782 // NOTE(shess): Crash directly rather than using NOTREACHED() so |
| 783 // that the signature is easier to triage in crash reports. |
| 784 // |
| 785 // Linker's ICF feature may merge this function with other functions with the |
| 786 // same definition and it may confuse the crash report processing system. |
| 787 static int static_variable_to_make_this_function_unique = 0; |
| 788 base::debug::Alias(&static_variable_to_make_this_function_unique); |
| 789 |
| 790 volatile int* zero = nullptr; |
| 791 *zero = 0; |
| 792 } |
| 793 |
| 794 NOINLINE void BadCastCrashIntentionally() { |
| 795 class A { |
| 796 virtual void f() {} |
| 797 }; |
| 798 |
| 799 class B { |
| 800 virtual void f() {} |
| 801 }; |
| 802 |
| 803 A a; |
| 804 (void)(B*) & a; |
| 805 } |
| 806 |
| 807 #if defined(ADDRESS_SANITIZER) || defined(SYZYASAN) |
| 808 NOINLINE void MaybeTriggerAsanError(const GURL& url) { |
| 809 // NOTE(rogerm): We intentionally perform an invalid heap access here in |
| 810 // order to trigger an Address Sanitizer (ASAN) error report. |
| 811 const char kCrashDomain[] = "crash"; |
| 812 const char kHeapOverflow[] = "/heap-overflow"; |
| 813 const char kHeapUnderflow[] = "/heap-underflow"; |
| 814 const char kUseAfterFree[] = "/use-after-free"; |
| 815 #if defined(SYZYASAN) |
| 816 const char kCorruptHeapBlock[] = "/corrupt-heap-block"; |
| 817 const char kCorruptHeap[] = "/corrupt-heap"; |
| 818 #endif |
| 819 |
| 820 if (!url.DomainIs(kCrashDomain)) |
| 821 return; |
| 822 |
| 823 if (!url.has_path()) |
| 824 return; |
| 825 |
| 826 std::string crash_type(url.path()); |
| 827 if (crash_type == kHeapOverflow) { |
| 828 LOG(ERROR) << "Intentionally causing ASAN heap overflow" |
| 829 << " because user navigated to " << url.spec(); |
| 830 base::debug::AsanHeapOverflow(); |
| 831 } else if (crash_type == kHeapUnderflow) { |
| 832 LOG(ERROR) << "Intentionally causing ASAN heap underflow" |
| 833 << " because user navigated to " << url.spec(); |
| 834 base::debug::AsanHeapUnderflow(); |
| 835 } else if (crash_type == kUseAfterFree) { |
| 836 LOG(ERROR) << "Intentionally causing ASAN heap use-after-free" |
| 837 << " because user navigated to " << url.spec(); |
| 838 base::debug::AsanHeapUseAfterFree(); |
| 839 #if defined(SYZYASAN) |
| 840 } else if (crash_type == kCorruptHeapBlock) { |
| 841 LOG(ERROR) << "Intentionally causing ASAN corrupt heap block" |
| 842 << " because user navigated to " << url.spec(); |
| 843 base::debug::AsanCorruptHeapBlock(); |
| 844 } else if (crash_type == kCorruptHeap) { |
| 845 LOG(ERROR) << "Intentionally causing ASAN corrupt heap" |
| 846 << " because user navigated to " << url.spec(); |
| 847 base::debug::AsanCorruptHeap(); |
| 848 #endif |
| 849 } |
| 850 } |
| 851 #endif // ADDRESS_SANITIZER || SYZYASAN |
| 852 |
| 853 void MaybeHandleDebugURL(const GURL& url) { |
| 854 if (!url.SchemeIs(kChromeUIScheme)) |
| 855 return; |
| 856 if (url == kChromeUIBadCastCrashURL) { |
| 857 LOG(ERROR) << "Intentionally crashing (with bad cast)" |
| 858 << " because user navigated to " << url.spec(); |
| 859 BadCastCrashIntentionally(); |
| 860 } else if (url == kChromeUICrashURL) { |
| 861 LOG(ERROR) << "Intentionally crashing (with null pointer dereference)" |
| 862 << " because user navigated to " << url.spec(); |
| 863 CrashIntentionally(); |
| 864 } else if (url == kChromeUIDumpURL) { |
| 865 // This URL will only correctly create a crash dump file if content is |
| 866 // hosted in a process that has correctly called |
| 867 // base::debug::SetDumpWithoutCrashingFunction. Refer to the documentation |
| 868 // of base::debug::DumpWithoutCrashing for more details. |
| 869 base::debug::DumpWithoutCrashing(); |
| 870 } else if (url == kChromeUIKillURL) { |
| 871 LOG(ERROR) << "Intentionally issuing kill signal to current process" |
| 872 << " because user navigated to " << url.spec(); |
| 873 base::Process::Current().Terminate(1, false); |
| 874 } else if (url == kChromeUIHangURL) { |
| 875 LOG(ERROR) << "Intentionally hanging ourselves with sleep infinite loop" |
| 876 << " because user navigated to " << url.spec(); |
| 877 for (;;) { |
| 878 base::PlatformThread::Sleep(base::TimeDelta::FromSeconds(1)); |
| 879 } |
| 880 } else if (url == kChromeUIShorthangURL) { |
| 881 LOG(ERROR) << "Intentionally sleeping renderer for 20 seconds" |
| 882 << " because user navigated to " << url.spec(); |
| 883 base::PlatformThread::Sleep(base::TimeDelta::FromSeconds(20)); |
| 884 } else if (url == kChromeUIMemoryExhaustURL) { |
| 885 LOG(ERROR) |
| 886 << "Intentionally exhausting renderer memory because user navigated to " |
| 887 << url.spec(); |
| 888 ExhaustMemory(); |
| 889 } else if (url == kChromeUICheckCrashURL) { |
| 890 LOG(ERROR) << "Intentionally causing CHECK because user navigated to " |
| 891 << url.spec(); |
| 892 CHECK(false); |
| 893 } |
| 894 |
| 895 #if defined(ADDRESS_SANITIZER) || defined(SYZYASAN) |
| 896 MaybeTriggerAsanError(url); |
| 897 #endif // ADDRESS_SANITIZER || SYZYASAN |
| 898 } |
| 899 |
905 struct RenderFrameImpl::PendingFileChooser { | 900 struct RenderFrameImpl::PendingFileChooser { |
906 PendingFileChooser(const FileChooserParams& p, | 901 PendingFileChooser(const FileChooserParams& p, |
907 blink::WebFileChooserCompletion* c) | 902 blink::WebFileChooserCompletion* c) |
908 : params(p), completion(c) {} | 903 : params(p), completion(c) {} |
909 FileChooserParams params; | 904 FileChooserParams params; |
910 blink::WebFileChooserCompletion* completion; // MAY BE NULL to skip callback. | 905 blink::WebFileChooserCompletion* completion; // MAY BE NULL to skip callback. |
911 }; | 906 }; |
912 | 907 |
913 // static | 908 // static |
914 RenderFrameImpl* RenderFrameImpl::Create(RenderViewImpl* render_view, | 909 RenderFrameImpl* RenderFrameImpl::Create(RenderViewImpl* render_view, |
(...skipping 6055 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6970 policy(info.defaultPolicy), | 6965 policy(info.defaultPolicy), |
6971 replaces_current_history_item(info.replacesCurrentHistoryItem), | 6966 replaces_current_history_item(info.replacesCurrentHistoryItem), |
6972 history_navigation_in_new_child_frame( | 6967 history_navigation_in_new_child_frame( |
6973 info.isHistoryNavigationInNewChildFrame), | 6968 info.isHistoryNavigationInNewChildFrame), |
6974 client_redirect(info.isClientRedirect), | 6969 client_redirect(info.isClientRedirect), |
6975 cache_disabled(info.isCacheDisabled), | 6970 cache_disabled(info.isCacheDisabled), |
6976 form(info.form), | 6971 form(info.form), |
6977 source_location(info.sourceLocation) {} | 6972 source_location(info.sourceLocation) {} |
6978 | 6973 |
6979 } // namespace content | 6974 } // namespace content |
OLD | NEW |