chromium/third_party/blink/common/rust_crash/src/lib.rs

// Copyright 2023 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

//! Code to generate an artificial Rust panic to exercise our crash handling
//! logic and ensure it works for Rust crashes.

#[cxx::bridge(namespace = "blink")]
mod ffi {
    extern "Rust" {
        fn crash_in_rust(); // step 1 of main crash trigger. We bounce back to C++
        // then back to Rust to ensure crossing the language
        // boundary in both directions is represented in crash
        // dumps.
        fn reenter_rust(); // step 3

        fn crash_in_rust_with_overflow(); // separate crash trigger
    }

    #[namespace = "blink"]
    unsafe extern "C++" {
        include!("third_party/blink/common/rust_crash/rust_crash.h");
        fn EnterCppForRustCrash(); // step 2
    }
}

/// Create a crash within Rust code. This will call into C++ first
/// then return to Rust to ensure we can cope with fully mixed call stacks.
#[inline(never)]
fn crash_in_rust() {
    ffi::EnterCppForRustCrash();
}

#[inline(never)]
fn reenter_rust() {
    some_mod::another_rust_function();
}

/// Unnecessary mod to ensure reasonable representation of Rust
/// name mangled mods in our crash dumps.
mod some_mod {
    #[inline(never)]
    pub fn another_rust_function() {
        panic!("Crash from within Rust code.");
    }
}

/// Code that's only enabled if we're doing an ASAN build.
#[cfg(feature = "rust_crash_asan_enabled")]
#[inline(never)]
fn crash_in_rust_with_overflow() {
    let mut some_array = Box::new([1usize, 2usize, 3usize, 4usize]);
    let array_ptr = &mut some_array[0] as *mut usize;
    unsafe {
        let bad_array_ptr = array_ptr.offset(4);
        std::ptr::write_volatile(bad_array_ptr, 42);
    }
}

#[cfg(not(feature = "rust_crash_asan_enabled"))]
fn crash_in_rust_with_overflow() {
    unreachable!()
}