| 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 |