diff --git a/substrate/Cargo.lock b/substrate/Cargo.lock index a5cd455e6029b9b49d1ca30551d6b80612e2fe89..2db192dcbf1a165ab19b2174647467cdaf7f4cef 100644 --- a/substrate/Cargo.lock +++ b/substrate/Cargo.lock @@ -2250,6 +2250,7 @@ dependencies = [ "serde", "serde_json", "smallvec", + "sp-api", "sp-arithmetic", "sp-core", "sp-core-hashing-proc-macro", diff --git a/substrate/frame/support/Cargo.toml b/substrate/frame/support/Cargo.toml index ca26d3a5e32f20d38942801052d72caabcb1d09d..a69133961e9708a479d4ded7881b0bb2c72a2eb1 100644 --- a/substrate/frame/support/Cargo.toml +++ b/substrate/frame/support/Cargo.toml @@ -17,6 +17,7 @@ serde = { version = "1.0.136", optional = true, features = ["derive"] } codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive", "max-encoded-len"] } scale-info = { version = "2.1.1", default-features = false, features = ["derive"] } frame-metadata = { version = "15.0.0", default-features = false, features = ["v14"] } +sp-api = { version = "4.0.0-dev", default-features = false, path = "../../primitives/api" } sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } sp-io = { version = "6.0.0", default-features = false, path = "../../primitives/io" } sp-runtime = { version = "6.0.0", default-features = false, path = "../../primitives/runtime" } @@ -49,6 +50,7 @@ default = ["std"] std = [ "once_cell", "serde", + "sp-api/std", "sp-io/std", "codec/std", "scale-info/std", diff --git a/substrate/frame/support/src/traits/misc.rs b/substrate/frame/support/src/traits/misc.rs index ddb7f6f41b378bc1d17c09f2b894dab23d5f4416..fa59fa92f920d0f57640c786832828261f21cb87 100644 --- a/substrate/frame/support/src/traits/misc.rs +++ b/substrate/frame/support/src/traits/misc.rs @@ -18,7 +18,7 @@ //! Smaller traits used in FRAME which don't need their own file. use crate::dispatch::Parameter; -use codec::{CompactLen, Decode, DecodeAll, Encode, EncodeLike, Input, MaxEncodedLen}; +use codec::{CompactLen, Decode, DecodeLimit, Encode, EncodeLike, Input, MaxEncodedLen}; use scale_info::{build::Fields, meta_type, Path, Type, TypeInfo, TypeParameter}; use sp_arithmetic::traits::{CheckedAdd, CheckedMul, CheckedSub, Saturating}; #[doc(hidden)] @@ -745,7 +745,10 @@ impl<T: Encode> Encode for WrapperOpaque<T> { impl<T: Decode> Decode for WrapperOpaque<T> { fn decode<I: Input>(input: &mut I) -> Result<Self, codec::Error> { - Ok(Self(T::decode_all(&mut &<Vec<u8>>::decode(input)?[..])?)) + Ok(Self(T::decode_all_with_depth_limit( + sp_api::MAX_EXTRINSIC_DEPTH, + &mut &<Vec<u8>>::decode(input)?[..], + )?)) } fn skip<I: Input>(input: &mut I) -> Result<(), codec::Error> { @@ -807,7 +810,7 @@ impl<T: Decode> WrapperKeepOpaque<T> { /// /// Returns `None` if the decoding failed. pub fn try_decode(&self) -> Option<T> { - T::decode_all(&mut &self.data[..]).ok() + T::decode_all_with_depth_limit(sp_api::MAX_EXTRINSIC_DEPTH, &mut &self.data[..]).ok() } /// Returns the length of the encoded `T`. @@ -939,6 +942,30 @@ impl<Hash> PreimageRecipient<Hash> for () { #[cfg(test)] mod test { use super::*; + use sp_std::marker::PhantomData; + + #[derive(Encode, Decode)] + enum NestedType { + Nested(Box<Self>), + Done, + } + + #[test] + fn test_opaque_wrapper_decode_limit() { + let limit = sp_api::MAX_EXTRINSIC_DEPTH as usize; + let mut ok_bytes = vec![0u8; limit]; + ok_bytes.push(1u8); + let mut err_bytes = vec![0u8; limit + 1]; + err_bytes.push(1u8); + assert!(<WrapperOpaque<NestedType>>::decode(&mut &ok_bytes.encode()[..]).is_ok()); + assert!(<WrapperOpaque<NestedType>>::decode(&mut &err_bytes.encode()[..]).is_err()); + + let ok_keep_opaque = WrapperKeepOpaque { data: ok_bytes, _phantom: PhantomData }; + let err_keep_opaque = WrapperKeepOpaque { data: err_bytes, _phantom: PhantomData }; + + assert!(<WrapperKeepOpaque<NestedType>>::try_decode(&ok_keep_opaque).is_some()); + assert!(<WrapperKeepOpaque<NestedType>>::try_decode(&err_keep_opaque).is_none()); + } #[test] fn test_opaque_wrapper() {