From 29fa0a369d28eedbf6741a7699ce257175275029 Mon Sep 17 00:00:00 2001
From: Shawn Tabrizi <shawntabrizi@gmail.com>
Date: Thu, 17 Jun 2021 12:51:36 +0100
Subject: [PATCH] Add XCM Decode Limit (#3273)

* Add XCM Decode Limit of 256

* use `decode_all_*`

* Update xcm/src/double_encoded.rs
---
 polkadot/xcm/src/double_encoded.rs | 17 ++++++++++++++---
 1 file changed, 14 insertions(+), 3 deletions(-)

diff --git a/polkadot/xcm/src/double_encoded.rs b/polkadot/xcm/src/double_encoded.rs
index d9ba93d7d6e..4bd5dc0eb59 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 <http://www.gnu.org/licenses/>.
 
 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<T: Decode> DoubleEncoded<T> {
 	/// 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<T, ()> {
-		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.
-- 
GitLab