From fcd2c18dd321c2fbece40cc1f319e450a49b0a6c Mon Sep 17 00:00:00 2001 From: Alexander Gryaznov Date: Mon, 5 Dec 2022 17:40:13 +0200 Subject: [PATCH 1/5] Add debug buffer limit + enforcement Add debug buffer limit + enforcement --- frame/contracts/src/exec.rs | 67 +++++++++++++++++++++++++---- frame/contracts/src/schedule.rs | 4 ++ frame/contracts/src/wasm/mod.rs | 4 +- frame/contracts/src/wasm/runtime.rs | 4 +- 4 files changed, 67 insertions(+), 12 deletions(-) diff --git a/frame/contracts/src/exec.rs b/frame/contracts/src/exec.rs index 2884779d8fda7..dcb7ab460881a 100644 --- a/frame/contracts/src/exec.rs +++ b/frame/contracts/src/exec.rs @@ -24,6 +24,7 @@ use crate::{ use frame_support::{ crypto::ecdsa::ECDSAExt, dispatch::{DispatchError, DispatchResult, DispatchResultWithPostInfo, Dispatchable}, + ensure, storage::{with_transaction, TransactionOutcome}, traits::{Contains, Currency, ExistenceRequirement, OriginTrait, Randomness, Time}, weights::Weight, @@ -279,7 +280,7 @@ pub trait Ext: sealing::Sealed { /// when the code is executing on-chain. /// /// Returns `true` if debug message recording is enabled. Otherwise `false` is returned. - fn append_debug_buffer(&mut self, msg: &str) -> bool; + fn append_debug_buffer(&mut self, msg: &str) -> Result; /// Call some dispatchable and return the result. fn call_runtime(&self, call: ::RuntimeCall) -> DispatchResultWithPostInfo; @@ -1334,14 +1335,19 @@ where &mut self.top_frame_mut().nested_gas } - fn append_debug_buffer(&mut self, msg: &str) -> bool { + fn append_debug_buffer(&mut self, msg: &str) -> Result { if let Some(buffer) = &mut self.debug_message { if !msg.is_empty() { + ensure!( + buffer.len().checked_add(msg.len()).ok_or(())? <= + self.schedule.limits.debug_buffer_len as usize, + () + ); buffer.extend(msg.as_bytes()); } - true + Ok(true) } else { - false + Ok(false) } } @@ -2499,8 +2505,12 @@ mod tests { #[test] fn printing_works() { let code_hash = MockLoader::insert(Call, |ctx, _| { - ctx.ext.append_debug_buffer("This is a test"); - ctx.ext.append_debug_buffer("More text"); + ctx.ext + .append_debug_buffer("This is a test") + .expect("Maximum allowed debug buffer size exhausted!"); + ctx.ext + .append_debug_buffer("More text") + .expect("Maximum allowed debug buffer size exhausted!"); exec_success() }); @@ -2533,8 +2543,12 @@ mod tests { #[test] fn printing_works_on_fail() { let code_hash = MockLoader::insert(Call, |ctx, _| { - ctx.ext.append_debug_buffer("This is a test"); - ctx.ext.append_debug_buffer("More text"); + ctx.ext + .append_debug_buffer("This is a test") + .expect("Maximum allowed debug buffer size exhausted!"); + ctx.ext + .append_debug_buffer("More text") + .expect("Maximum allowed debug buffer size exhausted!"); exec_trapped() }); @@ -2564,6 +2578,43 @@ mod tests { assert_eq!(&String::from_utf8(debug_buffer).unwrap(), "This is a testMore text"); } + #[test] + fn debug_buffer_is_limited() { + let schedule: Schedule = ::Schedule::get(); + let code_hash = MockLoader::insert(Call, move |ctx, _| { + ctx.ext.append_debug_buffer("overflowing bytes").map_err(|_| { + DispatchError::Other("Maximum allowed debug buffer size exhausted!") + })?; + exec_success() + }); + + // Pre-fill the buffer up to its limit + let mut debug_buffer = vec![0u8; schedule.limits.debug_buffer_len as usize]; + + ExtBuilder::default().build().execute_with(|| { + let min_balance = ::Currency::minimum_balance(); + let mut gas_meter = GasMeter::::new(GAS_LIMIT); + set_balance(&ALICE, min_balance * 10); + place_contract(&BOB, code_hash); + let mut storage_meter = storage::meter::Meter::new(&ALICE, Some(0), 0).unwrap(); + assert_err!( + MockStack::run_call( + ALICE, + BOB, + &mut gas_meter, + &mut storage_meter, + &schedule, + 0, + vec![], + Some(&mut debug_buffer), + Determinism::Deterministic, + ) + .map_err(|e| e.error), + DispatchError::Other("Maximum allowed debug buffer size exhausted!") + ); + }); + } + #[test] fn call_reentry_direct_recursion() { // call the contract passed as input with disabled reentry diff --git a/frame/contracts/src/schedule.rs b/frame/contracts/src/schedule.rs index 79f9f49e58190..1c7643cbd7dc6 100644 --- a/frame/contracts/src/schedule.rs +++ b/frame/contracts/src/schedule.rs @@ -147,6 +147,9 @@ pub struct Limits { /// The maximum size of a storage value and event payload in bytes. pub payload_len: u32, + + /// The maximum size of the debug buffer in bytes. + pub debug_buffer_len: u32, } impl Limits { @@ -530,6 +533,7 @@ impl Default for Limits { subject_len: 32, call_depth: 32, payload_len: 16 * 1024, + debug_buffer_len: 2 * 1024 * 1024, } } } diff --git a/frame/contracts/src/wasm/mod.rs b/frame/contracts/src/wasm/mod.rs index ac338007e5dc9..add256a0ba840 100644 --- a/frame/contracts/src/wasm/mod.rs +++ b/frame/contracts/src/wasm/mod.rs @@ -594,9 +594,9 @@ mod tests { fn gas_meter(&mut self) -> &mut GasMeter { &mut self.gas_meter } - fn append_debug_buffer(&mut self, msg: &str) -> bool { + fn append_debug_buffer(&mut self, msg: &str) -> Result { self.debug_buffer.extend(msg.as_bytes()); - true + Ok(true) } fn call_runtime( &self, diff --git a/frame/contracts/src/wasm/runtime.rs b/frame/contracts/src/wasm/runtime.rs index 988bb224f2a6c..3f19e4af6a34c 100644 --- a/frame/contracts/src/wasm/runtime.rs +++ b/frame/contracts/src/wasm/runtime.rs @@ -2392,11 +2392,11 @@ pub mod env { str_len: u32, ) -> Result { ctx.charge_gas(RuntimeCosts::DebugMessage)?; - if ctx.ext.append_debug_buffer("") { + if ctx.ext.append_debug_buffer("").map_err(|_| Error::::OutOfBounds)? { let data = ctx.read_sandbox_memory(memory, str_ptr, str_len)?; let msg = core::str::from_utf8(&data).map_err(|_| >::DebugMessageInvalidUTF8)?; - ctx.ext.append_debug_buffer(msg); + ctx.ext.append_debug_buffer(msg).map_err(|_| Error::::OutOfBounds)?; return Ok(ReturnCode::Success) } Ok(ReturnCode::LoggingDisabled) From b456323367238c31750f8ed6f89172d014a80a20 Mon Sep 17 00:00:00 2001 From: Alexander Gryaznov Date: Tue, 6 Dec 2022 19:57:59 +0200 Subject: [PATCH 2/5] use BoundedVec for the debug buffer --- bin/node/runtime/src/lib.rs | 1 + frame/contracts/src/exec.rs | 31 +++++++++++++------------------ frame/contracts/src/lib.rs | 21 ++++++++++++++------- frame/contracts/src/tests.rs | 1 + 4 files changed, 29 insertions(+), 25 deletions(-) diff --git a/bin/node/runtime/src/lib.rs b/bin/node/runtime/src/lib.rs index 633106e10b6f8..1cc030be972e4 100644 --- a/bin/node/runtime/src/lib.rs +++ b/bin/node/runtime/src/lib.rs @@ -1194,6 +1194,7 @@ impl pallet_contracts::Config for Runtime { type MaxCodeLen = ConstU32<{ 128 * 1024 }>; type MaxStorageKeyLen = ConstU32<128>; type UnsafeUnstableInterface = ConstBool; + type MaxDebugBufferLen = ConstU32<{ 2 * 1024 * 1024 }>; } impl pallet_sudo::Config for Runtime { diff --git a/frame/contracts/src/exec.rs b/frame/contracts/src/exec.rs index e0e8032b8efd8..4b30d6a027692 100644 --- a/frame/contracts/src/exec.rs +++ b/frame/contracts/src/exec.rs @@ -18,13 +18,12 @@ use crate::{ gas::GasMeter, storage::{self, Storage, WriteOutcome}, - BalanceOf, CodeHash, Config, ContractInfo, ContractInfoOf, Determinism, Error, Event, Nonce, - Pallet as Contracts, Schedule, + BalanceOf, CodeHash, Config, ContractInfo, ContractInfoOf, DebugBufferVec, Determinism, Error, + Event, Nonce, Pallet as Contracts, Schedule, }; use frame_support::{ crypto::ecdsa::ECDSAExt, dispatch::{DispatchError, DispatchResult, DispatchResultWithPostInfo, Dispatchable}, - ensure, storage::{with_transaction, TransactionOutcome}, traits::{Contains, Currency, ExistenceRequirement, OriginTrait, Randomness, Time}, weights::Weight, @@ -410,7 +409,7 @@ pub struct Stack<'a, T: Config, E> { /// /// All the bytes added to this field should be valid UTF-8. The buffer has no defined /// structure and is intended to be shown to users as-is for debugging purposes. - debug_message: Option<&'a mut Vec>, + debug_message: Option<&'a mut DebugBufferVec>, /// The determinism requirement of this call stack. determinism: Determinism, /// No executable is held by the struct but influences its behaviour. @@ -618,7 +617,7 @@ where schedule: &'a Schedule, value: BalanceOf, input_data: Vec, - debug_message: Option<&'a mut Vec>, + debug_message: Option<&'a mut DebugBufferVec>, determinism: Determinism, ) -> Result { let (mut stack, executable) = Self::new( @@ -653,7 +652,7 @@ where value: BalanceOf, input_data: Vec, salt: &[u8], - debug_message: Option<&'a mut Vec>, + debug_message: Option<&'a mut DebugBufferVec>, ) -> Result<(T::AccountId, ExecReturnValue), ExecError> { let (mut stack, executable) = Self::new( FrameArgs::Instantiate { @@ -682,7 +681,7 @@ where storage_meter: &'a mut storage::meter::Meter, schedule: &'a Schedule, value: BalanceOf, - debug_message: Option<&'a mut Vec>, + debug_message: Option<&'a mut DebugBufferVec>, determinism: Determinism, ) -> Result<(Self, E), ExecError> { let (first_frame, executable, nonce) = Self::new_frame( @@ -1332,12 +1331,7 @@ where fn append_debug_buffer(&mut self, msg: &str) -> Result { if let Some(buffer) = &mut self.debug_message { if !msg.is_empty() { - ensure!( - buffer.len().checked_add(msg.len()).ok_or(())? <= - self.schedule.limits.debug_buffer_len as usize, - () - ); - buffer.extend(msg.as_bytes()); + buffer.try_append(&mut msg.as_bytes().to_vec())?; } Ok(true) } else { @@ -2518,7 +2512,7 @@ mod tests { exec_success() }); - let mut debug_buffer = Vec::new(); + let mut debug_buffer = DebugBufferVec::::try_from(Vec::new()).unwrap(); ExtBuilder::default().build().execute_with(|| { let min_balance = ::Currency::minimum_balance(); @@ -2541,7 +2535,7 @@ mod tests { .unwrap(); }); - assert_eq!(&String::from_utf8(debug_buffer).unwrap(), "This is a testMore text"); + assert_eq!(&String::from_utf8(debug_buffer.to_vec()).unwrap(), "This is a testMore text"); } #[test] @@ -2556,7 +2550,7 @@ mod tests { exec_trapped() }); - let mut debug_buffer = Vec::new(); + let mut debug_buffer = DebugBufferVec::::try_from(Vec::new()).unwrap(); ExtBuilder::default().build().execute_with(|| { let min_balance = ::Currency::minimum_balance(); @@ -2579,7 +2573,7 @@ mod tests { assert!(result.is_err()); }); - assert_eq!(&String::from_utf8(debug_buffer).unwrap(), "This is a testMore text"); + assert_eq!(&String::from_utf8(debug_buffer.to_vec()).unwrap(), "This is a testMore text"); } #[test] @@ -2593,7 +2587,8 @@ mod tests { }); // Pre-fill the buffer up to its limit - let mut debug_buffer = vec![0u8; schedule.limits.debug_buffer_len as usize]; + let mut debug_buffer = + DebugBufferVec::::try_from(vec![0u8; DebugBufferVec::::bound()]).unwrap(); ExtBuilder::default().build().execute_with(|| { let min_balance = ::Currency::minimum_balance(); diff --git a/frame/contracts/src/lib.rs b/frame/contracts/src/lib.rs index 4bbb311313d61..bcdbce5e2eae2 100644 --- a/frame/contracts/src/lib.rs +++ b/frame/contracts/src/lib.rs @@ -142,6 +142,7 @@ type BalanceOf = type CodeVec = BoundedVec::MaxCodeLen>; type RelaxedCodeVec = WeakBoundedVec::MaxCodeLen>; type AccountIdLookupOf = <::Lookup as StaticLookup>::Source; +type DebugBufferVec = BoundedVec::MaxDebugBufferLen>; /// Used as a sentinel value when reading and writing contract memory. /// @@ -344,6 +345,10 @@ pub mod pallet { /// Do **not** set to `true` on productions chains. #[pallet::constant] type UnsafeUnstableInterface: Get; + + /// The maximum length of the debug buffer in bytes. + #[pallet::constant] + type MaxDebugBufferLen: Get; } #[pallet::hooks] @@ -952,7 +957,7 @@ where debug: bool, determinism: Determinism, ) -> ContractExecResult> { - let mut debug_message = if debug { Some(Vec::new()) } else { None }; + let mut debug_message = if debug { Some(DebugBufferVec::::default()) } else { None }; let output = Self::internal_call( origin, dest, @@ -968,7 +973,7 @@ where gas_consumed: output.gas_meter.gas_consumed(), gas_required: output.gas_meter.gas_required(), storage_deposit: output.storage_deposit, - debug_message: debug_message.unwrap_or_default(), + debug_message: debug_message.unwrap_or_default().to_vec(), } } @@ -994,7 +999,7 @@ where salt: Vec, debug: bool, ) -> ContractInstantiateResult> { - let mut debug_message = if debug { Some(Vec::new()) } else { None }; + let mut debug_message = if debug { Some(DebugBufferVec::::default()) } else { None }; let output = Self::internal_instantiate( origin, value, @@ -1013,7 +1018,7 @@ where gas_consumed: output.gas_meter.gas_consumed(), gas_required: output.gas_meter.gas_required(), storage_deposit: output.storage_deposit, - debug_message: debug_message.unwrap_or_default(), + debug_message: debug_message.unwrap_or_default().to_vec(), } } @@ -1104,7 +1109,7 @@ where gas_limit: Weight, storage_deposit_limit: Option>, data: Vec, - debug_message: Option<&mut Vec>, + debug_message: Option<&mut DebugBufferVec>, determinism: Determinism, ) -> InternalCallOutput { let mut gas_meter = GasMeter::new(gas_limit); @@ -1147,7 +1152,7 @@ where code: Code>, data: Vec, salt: Vec, - mut debug_message: Option<&mut Vec>, + mut debug_message: Option<&mut DebugBufferVec>, ) -> InternalInstantiateOutput { let mut storage_deposit = Default::default(); let mut gas_meter = GasMeter::new(gas_limit); @@ -1163,7 +1168,9 @@ where TryInstantiate::Skip, ) .map_err(|(err, msg)| { - debug_message.as_mut().map(|buffer| buffer.extend(msg.as_bytes())); + debug_message + .as_mut() + .map(|buffer| buffer.try_append(&mut msg.as_bytes().to_vec())); err })?; // The open deposit will be charged during execution when the diff --git a/frame/contracts/src/tests.rs b/frame/contracts/src/tests.rs index e5395c73d2868..a32c8d532a18c 100644 --- a/frame/contracts/src/tests.rs +++ b/frame/contracts/src/tests.rs @@ -415,6 +415,7 @@ impl Config for Test { type MaxCodeLen = ConstU32<{ 128 * 1024 }>; type MaxStorageKeyLen = ConstU32<128>; type UnsafeUnstableInterface = UnstableInterface; + type MaxDebugBufferLen = ConstU32<{ 2 * 1024 * 1024 }>; } pub const ALICE: AccountId32 = AccountId32::new([1u8; 32]); From cbd91a493cdc66c6084fbcc45b18521c479e59d8 Mon Sep 17 00:00:00 2001 From: Alexander Gryaznov Date: Tue, 6 Dec 2022 19:59:27 +0200 Subject: [PATCH 3/5] revert schedule (debug buf len limit not needed anymore) --- frame/contracts/src/schedule.rs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/frame/contracts/src/schedule.rs b/frame/contracts/src/schedule.rs index e9d2b09b8ede5..4f2d3b61d0176 100644 --- a/frame/contracts/src/schedule.rs +++ b/frame/contracts/src/schedule.rs @@ -153,9 +153,6 @@ pub struct Limits { /// The maximum size of a storage value and event payload in bytes. pub payload_len: u32, - - /// The maximum size of the debug buffer in bytes. - pub debug_buffer_len: u32, } impl Limits { @@ -544,7 +541,6 @@ impl Default for Limits { subject_len: 32, call_depth: 32, payload_len: 16 * 1024, - debug_buffer_len: 2 * 1024 * 1024, } } } From da651ea59c198fd5eb64431c01d4bf310b5c2a64 Mon Sep 17 00:00:00 2001 From: Alexander Gryaznov Date: Tue, 6 Dec 2022 20:15:49 +0200 Subject: [PATCH 4/5] return DispatchError --- frame/contracts/src/exec.rs | 14 +++++++------- frame/contracts/src/wasm/mod.rs | 2 +- frame/contracts/src/wasm/runtime.rs | 10 ++++++++-- 3 files changed, 16 insertions(+), 10 deletions(-) diff --git a/frame/contracts/src/exec.rs b/frame/contracts/src/exec.rs index 4b30d6a027692..7f608e0029445 100644 --- a/frame/contracts/src/exec.rs +++ b/frame/contracts/src/exec.rs @@ -279,7 +279,7 @@ pub trait Ext: sealing::Sealed { /// when the code is executing on-chain. /// /// Returns `true` if debug message recording is enabled. Otherwise `false` is returned. - fn append_debug_buffer(&mut self, msg: &str) -> Result; + fn append_debug_buffer(&mut self, msg: &str) -> Result; /// Call some dispatchable and return the result. fn call_runtime(&self, call: ::RuntimeCall) -> DispatchResultWithPostInfo; @@ -1328,10 +1328,12 @@ where &mut self.top_frame_mut().nested_gas } - fn append_debug_buffer(&mut self, msg: &str) -> Result { + fn append_debug_buffer(&mut self, msg: &str) -> Result { if let Some(buffer) = &mut self.debug_message { if !msg.is_empty() { - buffer.try_append(&mut msg.as_bytes().to_vec())?; + buffer.try_append(&mut msg.as_bytes().to_vec()).map_err(|_| { + DispatchError::Other("Maximum allowed debug buffer size exhausted!") + })?; } Ok(true) } else { @@ -2578,11 +2580,8 @@ mod tests { #[test] fn debug_buffer_is_limited() { - let schedule: Schedule = ::Schedule::get(); let code_hash = MockLoader::insert(Call, move |ctx, _| { - ctx.ext.append_debug_buffer("overflowing bytes").map_err(|_| { - DispatchError::Other("Maximum allowed debug buffer size exhausted!") - })?; + ctx.ext.append_debug_buffer("overflowing bytes")?; exec_success() }); @@ -2591,6 +2590,7 @@ mod tests { DebugBufferVec::::try_from(vec![0u8; DebugBufferVec::::bound()]).unwrap(); ExtBuilder::default().build().execute_with(|| { + let schedule: Schedule = ::Schedule::get(); let min_balance = ::Currency::minimum_balance(); let mut gas_meter = GasMeter::::new(GAS_LIMIT); set_balance(&ALICE, min_balance * 10); diff --git a/frame/contracts/src/wasm/mod.rs b/frame/contracts/src/wasm/mod.rs index 93ad16625e807..d85dac95cc712 100644 --- a/frame/contracts/src/wasm/mod.rs +++ b/frame/contracts/src/wasm/mod.rs @@ -594,7 +594,7 @@ mod tests { fn gas_meter(&mut self) -> &mut GasMeter { &mut self.gas_meter } - fn append_debug_buffer(&mut self, msg: &str) -> Result { + fn append_debug_buffer(&mut self, msg: &str) -> Result { self.debug_buffer.extend(msg.as_bytes()); Ok(true) } diff --git a/frame/contracts/src/wasm/runtime.rs b/frame/contracts/src/wasm/runtime.rs index 4b94d0ab3d4fc..af114701bbea6 100644 --- a/frame/contracts/src/wasm/runtime.rs +++ b/frame/contracts/src/wasm/runtime.rs @@ -2395,11 +2395,17 @@ pub mod env { str_len: u32, ) -> Result { ctx.charge_gas(RuntimeCosts::DebugMessage)?; - if ctx.ext.append_debug_buffer("").map_err(|_| Error::::OutOfBounds)? { + if ctx + .ext + .append_debug_buffer("") + .map_err(|err| TrapReason::SupervisorError(err))? + { let data = ctx.read_sandbox_memory(memory, str_ptr, str_len)?; let msg = core::str::from_utf8(&data).map_err(|_| >::DebugMessageInvalidUTF8)?; - ctx.ext.append_debug_buffer(msg).map_err(|_| Error::::OutOfBounds)?; + ctx.ext + .append_debug_buffer(msg) + .map_err(|err| TrapReason::SupervisorError(err))?; return Ok(ReturnCode::Success) } Ok(ReturnCode::LoggingDisabled) From aeca428ddeaaaab7b34c50f6435d099a382e0f65 Mon Sep 17 00:00:00 2001 From: Alexander Gryaznov Date: Wed, 7 Dec 2022 20:22:59 +0200 Subject: [PATCH 5/5] addressed review comments --- frame/contracts/src/exec.rs | 8 ++++---- frame/contracts/src/lib.rs | 7 ++++--- frame/contracts/src/wasm/runtime.rs | 10 ++-------- 3 files changed, 10 insertions(+), 15 deletions(-) diff --git a/frame/contracts/src/exec.rs b/frame/contracts/src/exec.rs index 7f608e0029445..945095dc20329 100644 --- a/frame/contracts/src/exec.rs +++ b/frame/contracts/src/exec.rs @@ -1331,9 +1331,9 @@ where fn append_debug_buffer(&mut self, msg: &str) -> Result { if let Some(buffer) = &mut self.debug_message { if !msg.is_empty() { - buffer.try_append(&mut msg.as_bytes().to_vec()).map_err(|_| { - DispatchError::Other("Maximum allowed debug buffer size exhausted!") - })?; + buffer + .try_extend(&mut msg.bytes()) + .map_err(|_| Error::::DebugBufferExhausted)?; } Ok(true) } else { @@ -2609,7 +2609,7 @@ mod tests { Determinism::Deterministic, ) .map_err(|e| e.error), - DispatchError::Other("Maximum allowed debug buffer size exhausted!") + Error::::DebugBufferExhausted ); }); } diff --git a/frame/contracts/src/lib.rs b/frame/contracts/src/lib.rs index bcdbce5e2eae2..a2e7e4adf3254 100644 --- a/frame/contracts/src/lib.rs +++ b/frame/contracts/src/lib.rs @@ -859,6 +859,9 @@ pub mod pallet { CodeRejected, /// An indetermistic code was used in a context where this is not permitted. Indeterministic, + /// The debug buffer size used during contract execution exceeded the limit determined by + /// the `MaxDebugBufferLen` pallet config parameter. + DebugBufferExhausted, } /// A mapping from an original code hash to the original code, untouched by instrumentation. @@ -1168,9 +1171,7 @@ where TryInstantiate::Skip, ) .map_err(|(err, msg)| { - debug_message - .as_mut() - .map(|buffer| buffer.try_append(&mut msg.as_bytes().to_vec())); + debug_message.as_mut().map(|buffer| buffer.try_extend(&mut msg.bytes())); err })?; // The open deposit will be charged during execution when the diff --git a/frame/contracts/src/wasm/runtime.rs b/frame/contracts/src/wasm/runtime.rs index af114701bbea6..50ad9996e6eb6 100644 --- a/frame/contracts/src/wasm/runtime.rs +++ b/frame/contracts/src/wasm/runtime.rs @@ -2395,17 +2395,11 @@ pub mod env { str_len: u32, ) -> Result { ctx.charge_gas(RuntimeCosts::DebugMessage)?; - if ctx - .ext - .append_debug_buffer("") - .map_err(|err| TrapReason::SupervisorError(err))? - { + if ctx.ext.append_debug_buffer("")? { let data = ctx.read_sandbox_memory(memory, str_ptr, str_len)?; let msg = core::str::from_utf8(&data).map_err(|_| >::DebugMessageInvalidUTF8)?; - ctx.ext - .append_debug_buffer(msg) - .map_err(|err| TrapReason::SupervisorError(err))?; + ctx.ext.append_debug_buffer(msg)?; return Ok(ReturnCode::Success) } Ok(ReturnCode::LoggingDisabled)