1*da093747SAlex Crichton use crate::prelude::*; 2*da093747SAlex Crichton use core::fmt; 3*da093747SAlex Crichton 4*da093747SAlex Crichton /// Helper macro to `bail!` with a `WasmtimeBug` instance. 5*da093747SAlex Crichton /// 6*da093747SAlex Crichton /// This is used in locations in lieu of panicking. The general idea when using 7*da093747SAlex Crichton /// this is: 8*da093747SAlex Crichton /// 9*da093747SAlex Crichton /// * The invocation of this cannot be refactored to be statically ruled out. 10*da093747SAlex Crichton /// * The invocation cannot be reasoned about locally to determine that this is 11*da093747SAlex Crichton /// dynamically not reachable. 12*da093747SAlex Crichton /// 13*da093747SAlex Crichton /// This macro serves as an alternative to `panic!` which returns a 14*da093747SAlex Crichton /// `WasmtimeBug` instead of panicking. This means that a trap is raised in the 15*da093747SAlex Crichton /// guest and a store is poisoned for example (w.r.t. components). This 16*da093747SAlex Crichton /// primarily serves as a DoS mitigation mechanism where if the panic were 17*da093747SAlex Crichton /// actually hit at runtime it would be a CVE. The worst-case scenario of 18*da093747SAlex Crichton /// raising a trap is that a guest is erroneously terminated, which is a much 19*da093747SAlex Crichton /// more controlled failure mode. 20*da093747SAlex Crichton /// 21*da093747SAlex Crichton /// The general guideline for using this is "don't" if you can avoid it because 22*da093747SAlex Crichton /// it's best to either statically rule out these cases or make it verifiable 23*da093747SAlex Crichton /// locally that it can't be hit. When this isn't possible, however, this is a 24*da093747SAlex Crichton /// good alternative to panicking in the case that this is actually executed at 25*da093747SAlex Crichton /// runtime. 26*da093747SAlex Crichton macro_rules! bail_bug { 27*da093747SAlex Crichton ($($arg:tt)*) => {{ 28*da093747SAlex Crichton // Minimize argument passing to the `new` function by placing the 29*da093747SAlex Crichton // file/line in a static which is passed by reference to just pass a 30*da093747SAlex Crichton // single extra pointer argument. 31*da093747SAlex Crichton static POS: (&'static str, u32) = (file!(), line!()); 32*da093747SAlex Crichton $crate::bail!(crate::WasmtimeBug::new(format_args!($($arg)*), &POS)) 33*da093747SAlex Crichton }} 34*da093747SAlex Crichton } 35*da093747SAlex Crichton 36*da093747SAlex Crichton pub(crate) use bail_bug; 37*da093747SAlex Crichton 38*da093747SAlex Crichton /// Error which indicates a bug in Wasmtime. 39*da093747SAlex Crichton /// 40*da093747SAlex Crichton /// This structure is used internally with Wasmtime for situations which are a 41*da093747SAlex Crichton /// bug in Wasmtime but not serious enough to raise a panic and unwind the 42*da093747SAlex Crichton /// current thread of execution. In these situations this is still considered a 43*da093747SAlex Crichton /// bug and a trap is raised to terminate a guest, and it's considered something 44*da093747SAlex Crichton /// that needs to be fixed in Wasmtime. 45*da093747SAlex Crichton #[derive(Debug)] 46*da093747SAlex Crichton pub struct WasmtimeBug { 47*da093747SAlex Crichton message: String, 48*da093747SAlex Crichton file: &'static str, 49*da093747SAlex Crichton line: u32, 50*da093747SAlex Crichton } 51*da093747SAlex Crichton 52*da093747SAlex Crichton impl WasmtimeBug { 53*da093747SAlex Crichton #[cold] new(message: fmt::Arguments<'_>, pos: &'static (&'static str, u32)) -> Self54*da093747SAlex Crichton pub(crate) fn new(message: fmt::Arguments<'_>, pos: &'static (&'static str, u32)) -> Self { 55*da093747SAlex Crichton if cfg!(debug_assertions) { 56*da093747SAlex Crichton panic!("BUG: {message}"); 57*da093747SAlex Crichton } 58*da093747SAlex Crichton Self { 59*da093747SAlex Crichton message: message.to_string(), 60*da093747SAlex Crichton file: pos.0, 61*da093747SAlex Crichton line: pos.1, 62*da093747SAlex Crichton } 63*da093747SAlex Crichton } 64*da093747SAlex Crichton } 65*da093747SAlex Crichton 66*da093747SAlex Crichton impl fmt::Display for WasmtimeBug { fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result67*da093747SAlex Crichton fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 68*da093747SAlex Crichton write!( 69*da093747SAlex Crichton f, 70*da093747SAlex Crichton "\ 71*da093747SAlex Crichton BUG: {} 72*da093747SAlex Crichton location: {}:{} 73*da093747SAlex Crichton version: {} 74*da093747SAlex Crichton 75*da093747SAlex Crichton This is a bug in Wasmtime that was not thought to be reachable. A panic is 76*da093747SAlex Crichton not happening to avoid taking down the thread, but this trap is being injected 77*da093747SAlex Crichton into WebAssembly guests to prevent their execution. The Wasmtime project would 78*da093747SAlex Crichton appreciate a bug report with a copy of this message to help investigate what 79*da093747SAlex Crichton happened. If you're able to provide a reproduction, that would be appreciated, 80*da093747SAlex Crichton but it is not necessary to do so and instead indicating that this is reachable 81*da093747SAlex Crichton is a sufficiently actionable bug for maintainers to investigate. 82*da093747SAlex Crichton 83*da093747SAlex Crichton ", 84*da093747SAlex Crichton self.message, 85*da093747SAlex Crichton self.file, 86*da093747SAlex Crichton self.line, 87*da093747SAlex Crichton env!("CARGO_PKG_VERSION"), 88*da093747SAlex Crichton ) 89*da093747SAlex Crichton } 90*da093747SAlex Crichton } 91*da093747SAlex Crichton 92*da093747SAlex Crichton impl core::error::Error for WasmtimeBug {} 93