Skip to content

Commit

Permalink
Early import of pending upstream commmit
Browse files Browse the repository at this point in the history
For Trusty we want to be able to reduce the recursion limit for CBOR
parsing, as the default is bigger than the normal stack limit in Trusty.

This change has been added upstream as commit 25174b7bc31f ("feat: add
from_reader_with_recursion_limit") from
enarx/ciborium#84, so it should be available in
the next release of ciborium.

Test: TreeHugger, local Trusty fuzzing build
Change-Id: Ie1ca9affc26927b2d83722b705d1e4c10200939f
  • Loading branch information
daviddrysdale committed Jun 14, 2023
1 parent 585dd3e commit 6bcf53c
Show file tree
Hide file tree
Showing 2 changed files with 69 additions and 1 deletion.
24 changes: 24 additions & 0 deletions src/de/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -831,3 +831,27 @@ where

T::deserialize(&mut reader)
}

/// Deserializes as CBOR from a type with [`impl ciborium_io::Read`](ciborium_io::Read), with
/// a specified maximum recursion limit. Inputs that are nested beyond the specified limit
/// will result in [`Error::RecursionLimitExceeded`] .
///
/// Set a high recursion limit at your own risk (of stack exhaustion)!
#[inline]
pub fn from_reader_with_recursion_limit<T: de::DeserializeOwned, R: Read>(
reader: R,
recurse_limit: usize,
) -> Result<T, Error<R::Error>>
where
R::Error: core::fmt::Debug,
{
let mut scratch = [0; 4096];

let mut reader = Deserializer {
decoder: reader.into(),
scratch: &mut scratch,
recurse: recurse_limit,
};

T::deserialize(&mut reader)
}
46 changes: 45 additions & 1 deletion tests/recursion.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
//! test each of these types here to ensure there is no stack overflow.
use ciborium::{
de::{from_reader, Error},
de::{from_reader, from_reader_with_recursion_limit, Error},
value::Value,
};

Expand Down Expand Up @@ -46,3 +46,47 @@ fn text() {
e => panic!("incorrect error: {:?}", e),
}
}

#[test]
fn array_limit() {
let bytes = [0x9f; 128 * 1024];
for limit in 16..256 {
match from_reader_with_recursion_limit::<Value, _>(&bytes[..], limit).unwrap_err() {
Error::RecursionLimitExceeded => (),
e => panic!("incorrect error with limit {}: {:?}", limit, e),
}
// Data that is nested beyond the limit should fail with `RecursionLimitExceeded`
match from_reader_with_recursion_limit::<Value, _>(&bytes[..limit + 1], limit).unwrap_err()
{
Error::RecursionLimitExceeded => (),
e => panic!("incorrect error with limit {}: {:?}", limit, e),
}
// Data that is nested within the limit fails with a different error.
match from_reader_with_recursion_limit::<Value, _>(&bytes[..limit], limit).unwrap_err() {
Error::Io(..) => (),
e => panic!("incorrect error with limit {}: {:?}", limit, e),
}
}
}

#[test]
fn map_limit() {
let bytes = [0xbf; 128 * 1024];
for limit in 16..256 {
match from_reader_with_recursion_limit::<Value, _>(&bytes[..], limit).unwrap_err() {
Error::RecursionLimitExceeded => (),
e => panic!("incorrect error with limit {}: {:?}", limit, e),
}
// Data that is nested beyond the limit should fail with `RecursionLimitExceeded`
match from_reader_with_recursion_limit::<Value, _>(&bytes[..limit + 1], limit).unwrap_err()
{
Error::RecursionLimitExceeded => (),
e => panic!("incorrect error with limit {}: {:?}", limit, e),
}
// Data that is nested within the limit fails with a different error.
match from_reader_with_recursion_limit::<Value, _>(&bytes[..limit], limit).unwrap_err() {
Error::Io(..) => (),
e => panic!("incorrect error with limit {}: {:?}", limit, e),
}
}
}

0 comments on commit 6bcf53c

Please sign in to comment.