cosmwasm_vm/errors/
communication_error.rs1use std::fmt::Debug;
2use thiserror::Error;
3
4use super::region_validation_error::RegionValidationError;
5use crate::memory::Region;
6
7#[derive(Error, Debug)]
9#[non_exhaustive]
10pub enum CommunicationError {
11 #[error(
12 "The Wasm memory address {} provided by the contract could not be dereferenced: {}",
13 offset,
14 msg
15 )]
16 DerefErr {
17 offset: u32,
19 msg: String,
20 },
21 #[error("Got an invalid value for iteration order: {}", value)]
22 InvalidOrder { value: i32 },
23 #[error("Got an invalid region: {}", source)]
24 InvalidRegion {
25 #[from]
26 source: RegionValidationError,
27 },
28 #[error("Got an invalid section: {}", msg)]
30 InvalidSection { msg: String },
31 #[error("Cannot decode UTF8 bytes into string: {}", msg)]
33 InvalidUtf8 { msg: String },
34 #[error("Region length too big. Got {}, limit {}", length, max_length)]
35 RegionLengthTooBig { length: usize, max_length: usize },
37 #[error("Region too small. Got {}, required {}", size, required)]
38 RegionTooSmall { size: usize, required: usize },
39 #[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)]
40 RegionAccessErr {
41 region: Region,
42 memory_size: usize,
44 },
45 #[error("Got a zero Wasm address")]
46 ZeroAddress {},
47}
48
49impl CommunicationError {
50 pub(crate) fn deref_err(offset: u32, msg: impl Into<String>) -> Self {
51 CommunicationError::DerefErr {
52 offset,
53 msg: msg.into(),
54 }
55 }
56
57 #[allow(dead_code)]
58 pub(crate) fn invalid_order(value: i32) -> Self {
59 CommunicationError::InvalidOrder { value }
60 }
61
62 pub(crate) fn invalid_section(msg: impl Into<String>) -> Self {
63 CommunicationError::InvalidSection { msg: msg.into() }
64 }
65
66 #[allow(dead_code)]
67 pub(crate) fn invalid_utf8(msg: impl ToString) -> Self {
68 CommunicationError::InvalidUtf8 {
69 msg: msg.to_string(),
70 }
71 }
72
73 pub(crate) fn region_length_too_big(length: usize, max_length: usize) -> Self {
74 CommunicationError::RegionLengthTooBig { length, max_length }
75 }
76
77 pub(crate) fn region_too_small(size: usize, required: usize) -> Self {
78 CommunicationError::RegionTooSmall { size, required }
79 }
80
81 pub(crate) fn region_access_err(region: Region, memory_size: usize) -> Self {
82 CommunicationError::RegionAccessErr {
83 region,
84 memory_size,
85 }
86 }
87
88 pub(crate) fn zero_address() -> Self {
89 CommunicationError::ZeroAddress {}
90 }
91}
92
93#[cfg(test)]
94mod tests {
95 use super::*;
96
97 #[test]
100 fn deref_err() {
101 let error = CommunicationError::deref_err(345, "broken stuff");
102 match error {
103 CommunicationError::DerefErr { offset, msg, .. } => {
104 assert_eq!(offset, 345);
105 assert_eq!(msg, "broken stuff");
106 }
107 e => panic!("Unexpected error: {e:?}"),
108 }
109 }
110
111 #[test]
112 fn invalid_order() {
113 let error = CommunicationError::invalid_order(-745);
114 match error {
115 CommunicationError::InvalidOrder { value, .. } => assert_eq!(value, -745),
116 e => panic!("Unexpected error: {e:?}"),
117 }
118 }
119
120 #[test]
121 fn invalid_utf8() {
122 let error = CommunicationError::invalid_utf8("broken");
123 match error {
124 CommunicationError::InvalidUtf8 { msg, .. } => assert_eq!(msg, "broken"),
125 e => panic!("Unexpected error: {e:?}"),
126 }
127 }
128
129 #[test]
130 fn region_length_too_big_works() {
131 let error = CommunicationError::region_length_too_big(50, 20);
132 match error {
133 CommunicationError::RegionLengthTooBig {
134 length, max_length, ..
135 } => {
136 assert_eq!(length, 50);
137 assert_eq!(max_length, 20);
138 }
139 e => panic!("Unexpected error: {e:?}"),
140 }
141 }
142
143 #[test]
144 fn region_too_small_works() {
145 let error = CommunicationError::region_too_small(12, 33);
146 match error {
147 CommunicationError::RegionTooSmall { size, required, .. } => {
148 assert_eq!(size, 12);
149 assert_eq!(required, 33);
150 }
151 e => panic!("Unexpected error: {e:?}"),
152 }
153 }
154
155 #[test]
156 fn zero_address() {
157 let error = CommunicationError::zero_address();
158 match error {
159 CommunicationError::ZeroAddress { .. } => {}
160 e => panic!("Unexpected error: {e:?}"),
161 }
162 }
163}