Skip to content

Commit

Permalink
fix
Browse files Browse the repository at this point in the history
  • Loading branch information
chenyan-dfinity committed Feb 7, 2024
1 parent a33dcc9 commit e78d125
Show file tree
Hide file tree
Showing 3 changed files with 17 additions and 20 deletions.
11 changes: 8 additions & 3 deletions rust/candid/src/de.rs
Original file line number Diff line number Diff line change
Expand Up @@ -725,7 +725,6 @@ impl<'de, 'a> de::Deserializer<'de> for &'a mut Deserializer<'de> {
where
V: Visitor<'de>,
{
self.dec_value_cost(1)?;
visitor.visit_newtype_struct(self)
}
fn deserialize_option<V>(self, visitor: V) -> Result<V::Value>
Expand Down Expand Up @@ -851,6 +850,7 @@ impl<'de, 'a> de::Deserializer<'de> for &'a mut Deserializer<'de> {
let expect = (ek.clone(), ev.clone());
let wire = (wk.clone(), wv.clone());
let len = Len::read(&mut self.input)?.0;
self.dec_value_cost(len)?;
visitor.visit_map(Compound::new(
self,
Style::Map { len, expect, wire },
Expand Down Expand Up @@ -1024,7 +1024,9 @@ impl<'de, 'a> de::SeqAccess<'de> for Compound<'a, 'de> {
if expect.is_empty() && wire.is_empty() {
return Ok(None);
}
self.de.dec_value_cost(1)?;
if !wire.is_empty() {
self.de.dec_value_cost(1)?;
}
self.de.expect_type = expect
.pop_front()
.map(|f| f.ty)
Expand Down Expand Up @@ -1054,15 +1056,16 @@ impl<'de, 'a> de::MapAccess<'de> for Compound<'a, 'de> {
match (expect.front(), wire.front()) {
(Some(e), Some(w)) => {
use std::cmp::Ordering;
self.de.dec_value_cost(1)?;
match e.id.get_id().cmp(&w.id.get_id()) {
Ordering::Equal => {
self.de.dec_value_cost(1)?;
self.de.set_field_name(e.id.clone());
self.de.expect_type = expect.pop_front().unwrap().ty;
self.de.wire_type = wire.pop_front().unwrap().ty;
}
Ordering::Less => {
// by subtyping rules, expect_type can only be opt, reserved or null.
self.de.value_cost += 1; // correct the later decrement from serialize_option of producing None.
let field = e.id.clone();
self.de.set_field_name(field.clone());
let expect = expect.pop_front().unwrap().ty;
Expand All @@ -1077,6 +1080,7 @@ impl<'de, 'a> de::MapAccess<'de> for Compound<'a, 'de> {
self.de.wire_type = TypeInner::Reserved.into();
}
Ordering::Greater => {
self.de.dec_value_cost(1)?;
self.de.set_field_name(Label::Named("_".to_owned()).into());
self.de.wire_type = wire.pop_front().unwrap().ty;
self.de.expect_type = TypeInner::Reserved.into();
Expand All @@ -1090,6 +1094,7 @@ impl<'de, 'a> de::MapAccess<'de> for Compound<'a, 'de> {
self.de.expect_type = TypeInner::Reserved.into();
}
(Some(e), None) => {
self.de.value_cost += 1; // correct the later decrement from serialize_option of producing None.
self.de.set_field_name(e.id.clone());
self.de.expect_type = expect.pop_front().unwrap().ty;
self.de.wire_type = TypeInner::Reserved.into();
Expand Down
12 changes: 9 additions & 3 deletions rust/candid/tests/serde.rs
Original file line number Diff line number Diff line change
Expand Up @@ -760,10 +760,16 @@ where
{
use candid::types::value::IDLValue;
let mut deserializer = candid::de::IDLDeserialize::new(bytes).unwrap();
let decoded = deserializer.get_value::<IDLValue>().unwrap();
let cost = deserializer.value_cost();
let _ = deserializer.get_value::<T>().unwrap();
let cost1 = deserializer.value_cost();
let _ = deserializer.done().unwrap();
assert_eq!(cost, decoded.cost());

let mut deserializer = candid::de::IDLDeserialize::new(bytes).unwrap();
let value = deserializer.get_value::<IDLValue>().unwrap();
let cost2 = deserializer.value_cost();
let _ = deserializer.done().unwrap();
assert_eq!(cost1, cost2);
assert_eq!(cost2, value.cost());
}
}

Expand Down
14 changes: 0 additions & 14 deletions test/spacebomb.test.did
Original file line number Diff line number Diff line change
Expand Up @@ -18,20 +18,6 @@ assert blob "DIDL\04\6c\03\01\7f\02\01\03\02\6c\01\01\70\6c\00\6d\00\01\03\80\94
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)";
Expand Down

0 comments on commit e78d125

Please sign in to comment.