From b233dbc2d2bcc79c9fc574dd5968269df680b073 Mon Sep 17 00:00:00 2001 From: Yan Chen <48968912+chenyan-dfinity@users.noreply.github.com> Date: Tue, 17 Oct 2023 11:15:40 -0700 Subject: [PATCH 1/2] fix error msg for empty type (#478) * fix error msg for empty type * fix --- Cargo.lock | 2 +- rust/candid/Cargo.toml | 2 +- rust/candid/src/de.rs | 6 +++++- rust/candid/src/types/value.rs | 3 +-- 4 files changed, 8 insertions(+), 5 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d0334fe3..6ed7a8b7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -257,7 +257,7 @@ checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" [[package]] name = "candid" -version = "0.9.9" +version = "0.9.10" dependencies = [ "anyhow", "arbitrary", diff --git a/rust/candid/Cargo.toml b/rust/candid/Cargo.toml index cd1aa777..5351fcbf 100644 --- a/rust/candid/Cargo.toml +++ b/rust/candid/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "candid" -version = "0.9.9" +version = "0.9.10" edition = "2021" authors = ["DFINITY Team"] description = "Candid is an interface description language (IDL) for interacting with canisters running on the Internet Computer." diff --git a/rust/candid/src/de.rs b/rust/candid/src/de.rs index 3e8404fe..036440c6 100644 --- a/rust/candid/src/de.rs +++ b/rust/candid/src/de.rs @@ -423,7 +423,11 @@ impl<'de> Deserializer<'de> { where V: Visitor<'de>, { - Err(Error::subtype("Cannot decode empty type")) + Err(if *self.wire_type == TypeInner::Empty { + Error::msg("Cannot decode empty type") + } else { + Error::subtype("Cannot decode empty type") + }) } fn deserialize_future<'a, V>(&'a mut self, visitor: V) -> Result where diff --git a/rust/candid/src/types/value.rs b/rust/candid/src/types/value.rs index 89ac3cf5..a2676218 100644 --- a/rust/candid/src/types/value.rs +++ b/rust/candid/src/types/value.rs @@ -451,8 +451,7 @@ impl<'de> Visitor<'de> for IDLValueVisitor { 5u8 => { use std::io::Read; let len = leb128::read::unsigned(&mut bytes).map_err(E::custom)? as usize; - let mut buf = Vec::new(); - buf.resize(len, 0); + let mut buf = vec![0; len]; bytes.read_exact(&mut buf).map_err(E::custom)?; let meth = String::from_utf8(buf).map_err(E::custom)?; let id = crate::Principal::try_from(bytes).map_err(E::custom)?; From c342311ffd6e9a34eeac35fd47e43e179c2b2d37 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Tue, 17 Oct 2023 20:33:49 +0200 Subject: [PATCH 2/2] Candid test suite: Write a few more spacebomb tests (#479) Co-authored-by: Yan Chen <48968912+chenyan-dfinity@users.noreply.github.com> --- test/construct.test.did | 5 ----- test/spacebomb.test.did | 47 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 47 insertions(+), 5 deletions(-) create mode 100644 test/spacebomb.test.did diff --git a/test/construct.test.did b/test/construct.test.did index d516b281..290f0cbe 100644 --- a/test/construct.test.did +++ b/test/construct.test.did @@ -62,11 +62,6 @@ assert blob "DIDL\01\6d\00\01\00\02\00\00" == "(vec { vec {}; vec {} })" : (V assert blob "DIDL\01\6d\00\01\00\02\00\00" == "(vec { vec {}; vec {} })" : (vec vec opt empty) "vec: non-recursive tree"; assert blob "DIDL\01\6d\7f\01\00\e8\07" : (vec null) "vec null"; assert blob "DIDL\01\6d\7f\01\00\e8\07" : (vec opt nat) "vec null <: vec opt nat"; -assert blob "DIDL\01\6d\7f\01\00\80\94\eb\dc\03" !: (vec opt nat) "space bomb: vec null <: vec opt nat"; -assert blob "DIDL\01\6d\70\01\00\80\94\eb\dc\03" !: (opt nat) "space bomb: send vec reserved to opt nat"; -assert blob "DIDL\04\6c\03\01\7f\02\01\03\02\6c\01\01\70\6c\00\6d\00\01\03\80\94\eb\dc\03" !: (vec record {null;record{reserved};record{}}) "space bomb: zero-sized record"; -assert blob "DIDL\02\6d\01\6d\7f\01\00\05\ff\ff\3f\ff\ff\3f\ff\ff\3f\ff\ff\3f\ff\ff\3f" !: (vec vec null) "space bomb: vec vec null"; -assert blob "DIDL\03\6c\01\d6\fc\a7\02\01\6d\02\6c\00\01\00\80\ad\e2\04" !: (vec record {}) "space bomb: vec record {}"; assert "(vec { 1; -1 })" !: (vec nat) "vec: type mismatch"; assert blob "DIDL\01\6d\7c\01\00" !: (vec int) "vec: too short"; assert blob "DIDL\01\6d\7c\01\00\02\01" !: (vec int) "vec: too short"; diff --git a/test/spacebomb.test.did b/test/spacebomb.test.did new file mode 100644 index 00000000..5c2d415c --- /dev/null +++ b/test/spacebomb.test.did @@ -0,0 +1,47 @@ + +// Space bomb tests + + +// Messages with more than 2_000_000 zero-length elements in vectors should be rejected + +// \80\94\eb\dc\03 is 1000_000_000 +// \80\ad\e2\04 is 10_000_000 +// \80\89\7a is 2_000_000 +// \ff\ff\3f is 1_048_575 +// \80\b5\18 is 400_000 + + +// Plain decoding (unused arguments) +assert blob "DIDL\01\6d\7f\01\00\80\94\eb\dc\03" !: () "vec null (extra argument)"; +assert blob "DIDL\01\6d\70\01\00\80\94\eb\dc\03" !: () "vec reserved (extra argument)"; +assert blob "DIDL\04\6c\03\01\7f\02\01\03\02\6c\01\01\70\6c\00\6d\00\01\03\80\94\eb\dc\03" !: () "zero-sized record (extra argument)"; +assert blob "DIDL\02\6d\01\6d\7f\01\00\05\ff\ff\3f\ff\ff\3f\ff\ff\3f\ff\ff\3f\ff\ff\3f" !: () "vec vec null (extra argument)"; +assert blob "DIDL\03\6c\01\d6\fc\a7\02\01\6d\02\6c\00\01\00\80\ad\e2\04" !: () "vec record {} (extra argument)"; + +// Messages with exactly 2_000_000 zero-length elements should succeed +assert blob "DIDL\01\6d\7f\01\00\80\89\7a" : () "vec null (exactly 2000000)"; +assert blob "DIDL\01\6d\70\01\00\80\89\7a" : () "vec reserved (exactly 2000000)"; +assert blob "DIDL\04\6c\03\01\7f\02\01\03\02\6c\01\01\70\6c\00\6d\00\01\03\80\89\7a" : () "zero-sized record (exactly 2000000)"; +assert blob "DIDL\02\6d\01\6d\7f\01\00\05\80\b5\18\80\b5\18\80\b5\18\80\b5\18\80\b5\18" : () "vec vec null (exactly 2000000)"; +assert blob "DIDL\03\6c\01\d6\fc\a7\02\01\6d\02\6c\00\01\00\80\89\7a" : () "vec record {} (exactly 2000000)"; + +// Messages with exactly 2_000_001 zero-length elements should fail +assert blob "DIDL\01\6d\7f\01\00\80\89\7b" !: () "vec null (exactly 2000001)"; +assert blob "DIDL\01\6d\70\01\00\80\89\7b" !: () "vec reserved (exactly 2000001)"; +assert blob "DIDL\04\6c\03\01\7f\02\01\03\02\6c\01\01\70\6c\00\6d\00\01\03\80\89\7b" !: () "zero-sized record (exactly 2000001)"; +assert blob "DIDL\02\6d\01\6d\7f\01\00\05\80\b5\18\80\b5\18\80\b5\18\80\b5\18\80\b5\19" !: () "vec vec null (exactly 2000001)"; +assert blob "DIDL\03\6c\01\d6\fc\a7\02\01\6d\02\6c\00\01\00\80\89\7b" !: () "vec record {} (exactly 2000001)"; + +// Decoding to actual type +assert blob "DIDL\01\6d\7f\01\00\80\94\eb\dc\03" !: (vec opt nat) "vec null (not ignored)"; +assert blob "DIDL\01\6d\70\01\00\80\94\eb\dc\03" !: (vec reserved) "vec reserved (not ignored)"; +assert blob "DIDL\04\6c\03\01\7f\02\01\03\02\6c\01\01\70\6c\00\6d\00\01\03\80\94\eb\dc\03" !: (vec record {null;record{reserved};record{}}) "zero-sized record (not ignored)"; +assert blob "DIDL\02\6d\01\6d\7f\01\00\05\ff\ff\3f\ff\ff\3f\ff\ff\3f\ff\ff\3f\ff\ff\3f" !: (vec vec null) "vec vec null (not ignored)"; +assert blob "DIDL\03\6c\01\d6\fc\a7\02\01\6d\02\6c\00\01\00\80\ad\e2\04" !: (vec record {}) "vec record {} (not ignored)"; + +// Decoding under opt +assert blob "DIDL\01\6d\7f\01\00\80\94\eb\dc\03" !: (opt nat) "vec null (subtyping)"; +assert blob "DIDL\01\6d\70\01\00\80\94\eb\dc\03" !: (opt nat) "vec reserved (subtyping)"; +assert blob "DIDL\04\6c\03\01\7f\02\01\03\02\6c\01\01\70\6c\00\6d\00\01\03\80\94\eb\dc\03" !: (opt nat) "zero-sized record (subtyping)"; +assert blob "DIDL\02\6d\01\6d\7f\01\00\05\ff\ff\3f\ff\ff\3f\ff\ff\3f\ff\ff\3f\ff\ff\3f" !: (vec opt nat) "vec vec null (subtyping)"; +assert blob "DIDL\03\6c\01\d6\fc\a7\02\01\6d\02\6c\00\01\00\80\ad\e2\04" !: (opt nat) "vec record {} (subtyping)";