Skip to content

Commit

Permalink
Enforce a decoding limit in MultiAssets (#1395)
Browse files Browse the repository at this point in the history
* Enforce a decoding limit in MultiAssets

* ".git/.scripts/commands/fmt/fmt.sh"

* Update polkadot/xcm/src/v3/multiasset.rs

Co-authored-by: Keith Yeung <[email protected]>

* Just use a BoundedVec

* Conflicts

---------

Co-authored-by: command-bot <>
Co-authored-by: Keith Yeung <[email protected]>
  • Loading branch information
franciscoaguirre and KiChjang authored Sep 5, 2023
1 parent 3369168 commit 51dcc9f
Showing 1 changed file with 33 additions and 5 deletions.
38 changes: 33 additions & 5 deletions polkadot/xcm/src/v3/multiasset.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ use core::{
};
use parity_scale_codec::{self as codec, Decode, Encode, MaxEncodedLen};
use scale_info::TypeInfo;
use bounded_collections::{BoundedVec, ConstU32};

/// A general identifier for an instance of a non-fungible asset class.
#[derive(
Expand Down Expand Up @@ -506,9 +507,8 @@ impl TryFrom<OldMultiAsset> for MultiAsset {
#[cfg_attr(feature = "std", derive(serde::Serialize, serde::Deserialize))]
pub struct MultiAssets(Vec<MultiAsset>);

/// Maximum number of items we expect in a single `MultiAssets` value. Note this is not (yet)
/// enforced, and just serves to provide a sensible `max_encoded_len` for `MultiAssets`.
const MAX_ITEMS_IN_MULTIASSETS: usize = 20;
/// Maximum number of items in a single `MultiAssets` value that can be decoded.
pub const MAX_ITEMS_IN_MULTIASSETS: usize = 20;

impl MaxEncodedLen for MultiAssets {
fn max_encoded_len() -> usize {
Expand All @@ -517,8 +517,9 @@ impl MaxEncodedLen for MultiAssets {
}

impl Decode for MultiAssets {
fn decode<I: codec::Input>(input: &mut I) -> Result<Self, parity_scale_codec::Error> {
Self::from_sorted_and_deduplicated(Vec::<MultiAsset>::decode(input)?)
fn decode<I: codec::Input>(input: &mut I) -> Result<Self, codec::Error> {
let bounded_instructions = BoundedVec::<MultiAsset, ConstU32<{ MAX_ITEMS_IN_MULTIASSETS as u32 }>>::decode(input)?;
Self::from_sorted_and_deduplicated(bounded_instructions.into_inner())
.map_err(|()| "Out of order".into())
}
}
Expand Down Expand Up @@ -974,4 +975,31 @@ mod tests {
let r = MultiAssets::from_sorted_and_deduplicated(mixed_bad);
assert!(r.is_err());
}

#[test]
fn decoding_respects_limit() {
use super::*;

// Having lots of one asset will work since they are deduplicated
let lots_of_one_asset: MultiAssets =
vec![(GeneralIndex(1), 1u128).into(); MAX_ITEMS_IN_MULTIASSETS + 1].into();
let encoded = lots_of_one_asset.encode();
assert!(MultiAssets::decode(&mut &encoded[..]).is_ok());

// Fewer assets than the limit works
let mut few_assets: MultiAssets = Vec::new().into();
for i in 0..MAX_ITEMS_IN_MULTIASSETS {
few_assets.push((GeneralIndex(i as u128), 1u128).into());
}
let encoded = few_assets.encode();
assert!(MultiAssets::decode(&mut &encoded[..]).is_ok());

// Having lots of different assets will not work
let mut too_many_different_assets: MultiAssets = Vec::new().into();
for i in 0..MAX_ITEMS_IN_MULTIASSETS + 1 {
too_many_different_assets.push((GeneralIndex(i as u128), 1u128).into());
}
let encoded = too_many_different_assets.encode();
assert!(MultiAssets::decode(&mut &encoded[..]).is_err());
}
}

0 comments on commit 51dcc9f

Please sign in to comment.