diff --git a/polkadot/xcm/src/double_encoded.rs b/polkadot/xcm/src/double_encoded.rs index d9ba93d7d6..4bd5dc0eb5 100644 --- a/polkadot/xcm/src/double_encoded.rs +++ b/polkadot/xcm/src/double_encoded.rs @@ -15,7 +15,10 @@ // along with Polkadot. If not, see . use alloc::vec::Vec; -use parity_scale_codec::{Encode, Decode}; +use parity_scale_codec::{Encode, Decode, DecodeLimit}; + +/// Maximum nesting level for XCM decoding. +pub const MAX_XCM_DECODE_DEPTH: u32 = 8; /// Wrapper around the encoded and decoded versions of a value. /// Caches the decoded value once computed. @@ -69,14 +72,22 @@ impl DoubleEncoded { /// Returns a reference to the value in case of success and `Err(())` in case the decoding fails. pub fn ensure_decoded(&mut self) -> Result<&T, ()> { if self.decoded.is_none() { - self.decoded = T::decode(&mut &self.encoded[..]).ok(); + self.decoded = T::decode_all_with_depth_limit( + MAX_XCM_DECODE_DEPTH, + &mut &self.encoded[..], + ).ok(); } self.decoded.as_ref().ok_or(()) } /// Move the decoded value out or (if not present) decode `encoded`. pub fn take_decoded(&mut self) -> Result { - self.decoded.take().or_else(|| T::decode(&mut &self.encoded[..]).ok()).ok_or(()) + self.decoded.take().or_else(|| { + T::decode_all_with_depth_limit( + MAX_XCM_DECODE_DEPTH, + &mut &self.encoded[..], + ).ok() + }).ok_or(()) } /// Provides an API similar to `TryInto` that allows fallible conversion to the inner value type.