cosmwasm_vm/errors/
communication_error.rsuse std::fmt::Debug;
use thiserror::Error;
use super::region_validation_error::RegionValidationError;
use crate::memory::Region;
#[derive(Error, Debug)]
#[non_exhaustive]
pub enum CommunicationError {
#[error(
"The Wasm memory address {} provided by the contract could not be dereferenced: {}",
offset,
msg
)]
DerefErr {
offset: u32,
msg: String,
},
#[error("Got an invalid value for iteration order: {}", value)]
InvalidOrder { value: i32 },
#[error("Got an invalid region: {}", source)]
InvalidRegion {
#[from]
source: RegionValidationError,
},
#[error("Got an invalid section: {}", msg)]
InvalidSection { msg: String },
#[error("Cannot decode UTF8 bytes into string: {}", msg)]
InvalidUtf8 { msg: String },
#[error("Region length too big. Got {}, limit {}", length, max_length)]
RegionLengthTooBig { length: usize, max_length: usize },
#[error("Region too small. Got {}, required {}", size, required)]
RegionTooSmall { size: usize, required: usize },
#[error("Tried to access memory of region {:?} in Wasm memory of size {} bytes. This typically happens when the given Region pointer does not point to a proper Region struct.", region, memory_size)]
RegionAccessErr {
region: Region,
memory_size: usize,
},
#[error("Got a zero Wasm address")]
ZeroAddress {},
}
impl CommunicationError {
pub(crate) fn deref_err(offset: u32, msg: impl Into<String>) -> Self {
CommunicationError::DerefErr {
offset,
msg: msg.into(),
}
}
#[allow(dead_code)]
pub(crate) fn invalid_order(value: i32) -> Self {
CommunicationError::InvalidOrder { value }
}
pub(crate) fn invalid_section(msg: impl Into<String>) -> Self {
CommunicationError::InvalidSection { msg: msg.into() }
}
#[allow(dead_code)]
pub(crate) fn invalid_utf8(msg: impl ToString) -> Self {
CommunicationError::InvalidUtf8 {
msg: msg.to_string(),
}
}
pub(crate) fn region_length_too_big(length: usize, max_length: usize) -> Self {
CommunicationError::RegionLengthTooBig { length, max_length }
}
pub(crate) fn region_too_small(size: usize, required: usize) -> Self {
CommunicationError::RegionTooSmall { size, required }
}
pub(crate) fn region_access_err(region: Region, memory_size: usize) -> Self {
CommunicationError::RegionAccessErr {
region,
memory_size,
}
}
pub(crate) fn zero_address() -> Self {
CommunicationError::ZeroAddress {}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn deref_err() {
let error = CommunicationError::deref_err(345, "broken stuff");
match error {
CommunicationError::DerefErr { offset, msg, .. } => {
assert_eq!(offset, 345);
assert_eq!(msg, "broken stuff");
}
e => panic!("Unexpected error: {e:?}"),
}
}
#[test]
fn invalid_order() {
let error = CommunicationError::invalid_order(-745);
match error {
CommunicationError::InvalidOrder { value, .. } => assert_eq!(value, -745),
e => panic!("Unexpected error: {e:?}"),
}
}
#[test]
fn invalid_utf8() {
let error = CommunicationError::invalid_utf8("broken");
match error {
CommunicationError::InvalidUtf8 { msg, .. } => assert_eq!(msg, "broken"),
e => panic!("Unexpected error: {e:?}"),
}
}
#[test]
fn region_length_too_big_works() {
let error = CommunicationError::region_length_too_big(50, 20);
match error {
CommunicationError::RegionLengthTooBig {
length, max_length, ..
} => {
assert_eq!(length, 50);
assert_eq!(max_length, 20);
}
e => panic!("Unexpected error: {e:?}"),
}
}
#[test]
fn region_too_small_works() {
let error = CommunicationError::region_too_small(12, 33);
match error {
CommunicationError::RegionTooSmall { size, required, .. } => {
assert_eq!(size, 12);
assert_eq!(required, 33);
}
e => panic!("Unexpected error: {e:?}"),
}
}
#[test]
fn zero_address() {
let error = CommunicationError::zero_address();
match error {
CommunicationError::ZeroAddress { .. } => {}
e => panic!("Unexpected error: {e:?}"),
}
}
}