From 25e364bf1f9e82927f166d54483647b227e10976 Mon Sep 17 00:00:00 2001 From: plusls Date: Fri, 27 Jun 2025 17:50:02 +0800 Subject: [PATCH] support unlimit stack depth --- rmp-serde/Cargo.toml | 1 + rmp-serde/src/decode.rs | 25 +++++++++++++++++-------- rmp-serde/tests/decode.rs | 29 +++++++++++++++++++++++++++++ 3 files changed, 47 insertions(+), 8 deletions(-) diff --git a/rmp-serde/Cargo.toml b/rmp-serde/Cargo.toml index 9d0ce32a..1a6746b9 100644 --- a/rmp-serde/Cargo.toml +++ b/rmp-serde/Cargo.toml @@ -23,6 +23,7 @@ rmp = { version = "0.8.14", path = "../rmp" } rmpv = { path = "../rmpv" } serde_bytes = "0.11.5" serde = { version = "1.0.197", features = ["derive"] } +serde_stacker = "0.1.12" [badges] maintenance = { status = "looking-for-maintainer" } diff --git a/rmp-serde/src/decode.rs b/rmp-serde/src/decode.rs index 4f3bee36..1e2a2485 100644 --- a/rmp-serde/src/decode.rs +++ b/rmp-serde/src/decode.rs @@ -53,12 +53,16 @@ pub enum Error { macro_rules! depth_count( ( $counter:expr, $expr:expr ) => { { - $counter -= 1; - if $counter == 0 { - return Err(Error::DepthLimitExceeded) + if let Some(counter) = &mut $counter { + *counter -= 1; + if *counter == 0 { + return Err(Error::DepthLimitExceeded) + } } let res = $expr; - $counter += 1; + if let Some(counter) = &mut $counter { + *counter += 1; + } res } } @@ -181,7 +185,7 @@ pub struct Deserializer { _config: PhantomData, is_human_readable: bool, marker: Option, - depth: u16, + depth: Option, } impl Deserializer { @@ -213,7 +217,7 @@ impl Deserializer, DefaultConfig> { is_human_readable: DefaultConfig.is_human_readable(), // Cached marker in case of deserializing optional values. marker: None, - depth: 1024, + depth: Some(1024), } } } @@ -294,7 +298,7 @@ where is_human_readable: DefaultConfig.is_human_readable(), _config: PhantomData, marker: None, - depth: 1024, + depth: Some(1024), } } @@ -310,7 +314,12 @@ impl<'de, R: ReadSlice<'de>, C: SerializerConfig> Deserializer { /// Changes the maximum nesting depth that is allowed #[inline(always)] pub fn set_max_depth(&mut self, depth: usize) { - self.depth = depth.min(u16::MAX as _) as u16; + self.depth = Some(depth.min(u16::MAX as _) as u16); + } + /// disable stack depth check + #[inline(always)] + pub fn set_depth_unlimit(&mut self) { + self.depth = None; } } diff --git a/rmp-serde/tests/decode.rs b/rmp-serde/tests/decode.rs index 6787f1c1..a4dc924f 100644 --- a/rmp-serde/tests/decode.rs +++ b/rmp-serde/tests/decode.rs @@ -567,3 +567,32 @@ fn fail_depth_limit() { other => panic!("unexpected result: {other:?}"), } } + + + +#[test] +fn depth_unlimit() { + #[allow(dead_code)] + struct Nested { + sub: Vec, + } + + impl<'de> de::Deserialize<'de> for Nested { + fn deserialize(de: D) -> Result + where D: de::Deserializer<'de> + { + let nested = Vec::deserialize(de)?; + Ok(Nested { sub: nested }) + } + } + let mut data = Vec::new(); + for _ in 0..(u16::MAX as u32 + 1) { + data.push(0x91u8); + } + + let mut reader = rmp_serde::Deserializer::new(Cursor::new(data)); + reader.set_depth_unlimit(); + let deserializer = serde_stacker::Deserializer::new(&mut reader); + let res = Nested::deserialize(deserializer); + if let decode::Error::DepthLimitExceeded = res.err().unwrap() { panic!("unexpected DepthLimitExceeded") } +}