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.