Skip to content

Commit

Permalink
Full range check in rest of API (#216)
Browse files Browse the repository at this point in the history
* Full range check in rest of API

Check ranges and error on incorrect ones in constructors and setters in
all spots.

Additional non-deserialization test checks to check the above.

Migrate few remaining usage of `JsValue` for WASM errors away to `JsError`
to be consistent with the rest of the generated code.

* fixed clippy warnings (did cargo update? doesn't trigger locally and this is not recently changed code)
  • Loading branch information
rooooooooob authored Dec 12, 2023
1 parent 9c69b1f commit 45071ae
Show file tree
Hide file tree
Showing 8 changed files with 351 additions and 123 deletions.
414 changes: 297 additions & 117 deletions src/generation.rs

Large diffs are not rendered by default.

12 changes: 10 additions & 2 deletions src/intermediate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -807,7 +807,7 @@ impl FixedValue {
}
}

#[derive(Clone, Debug, Eq, PartialEq)]
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub enum Primitive {
Bool,
F64,
Expand Down Expand Up @@ -856,7 +856,7 @@ impl ToString for Primitive {
}
// TODO: impl display or fmt or whatever rust uses
impl Primitive {
pub fn to_variant(&self) -> VariantIdent {
pub fn to_variant(self) -> VariantIdent {
VariantIdent::new_custom(match self {
Primitive::Bool => "Bool",
Primitive::F32 => "F32",
Expand Down Expand Up @@ -1343,6 +1343,14 @@ impl RustType {
}
}

pub fn needs_bounds_check_if_inlined(&self, types: &IntermediateTypes) -> bool {
self.config.bounds.is_some()
|| match self.resolve_alias_shallow() {
ConceptualRustType::Rust(ident) => types.can_new_fail(ident),
_ => false,
}
}

fn _cbor_special_type(&self) -> Option<CBORSpecial> {
unimplemented!()
}
Expand Down
2 changes: 1 addition & 1 deletion src/parsing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ fn parse_type_choices(
types: &mut IntermediateTypes,
parent_visitor: &ParentVisitor,
name: &RustIdent,
type_choices: &Vec<TypeChoice>,
type_choices: &[TypeChoice],
tag: Option<usize>,
generic_params: Option<Vec<RustIdent>>,
cli: &Cli,
Expand Down
12 changes: 12 additions & 0 deletions tests/core/input.cddl
Original file line number Diff line number Diff line change
Expand Up @@ -159,4 +159,16 @@ bounds = [
z: text .size (3..14),
a: [* uint] .size (1..3),
b: { * uint => uint } .le 3
]

bounds_type_choice = bytes .size (0..64)
/ text .size (0..64)

bounds_group_choice = [
; @name a
a: uint, b: text .le 4 //
; @name b
hash //
; @name c
1, x: hash, y: hash
]
9 changes: 8 additions & 1 deletion tests/core/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -301,7 +301,7 @@ mod tests {

#[test]
fn bounds() {
deser_test(&Bounds::new(10, 5, 3, "abc".to_owned(), vec![5], [(0, 1), (2, 3)].into()));
deser_test(&Bounds::new(10, 5, 4, "abc".to_owned(), vec![5], [(0, 1), (2, 3)].into()).unwrap());
enum OOB {
Below,
Lower,
Expand Down Expand Up @@ -373,6 +373,13 @@ mod tests {
assert!(make_bounds(OOB::Lower, OOB::Upper, OOB::Lower, OOB::Upper, OOB::Above, OOB::Upper).is_err());
// b oob
assert!(make_bounds(OOB::Lower, OOB::Upper, OOB::Lower, OOB::Upper, OOB::Upper, OOB::Above).is_err());

// type and group choices share the same deserialization code so we only check the API
assert!(BoundsTypeChoice::new_bytes(vec![0; 64]).is_ok());
assert!(BoundsTypeChoice::new_bytes(vec![0; 65]).is_err());
assert!(BoundsGroupChoice::new_a(0, "four".to_owned()).is_ok());
assert!(BoundsGroupChoice::new_a(0, "hello".to_owned()).is_err());
deser_test(&BoundsGroupChoice::new_c(Hash::new(vec![]).unwrap(), Hash::new(vec![]).unwrap()));
}

#[test]
Expand Down
4 changes: 2 additions & 2 deletions tests/external_wasm_defs
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,10 @@ impl ExternalFoo {
cddl_lib::serialization::ToCBORBytes::to_cbor_bytes(&self.0)
}

pub fn from_cbor_bytes(cbor_bytes: &[u8]) -> Result<ExternalFoo, JsValue> {
pub fn from_cbor_bytes(cbor_bytes: &[u8]) -> Result<ExternalFoo, JsError> {
cddl_lib::serialization::Deserialize::from_cbor_bytes(cbor_bytes)
.map(Self)
.map_err(|e| JsValue::from_str(&format!("from_bytes: {}", e)))
.map_err(Into::into)
}

pub fn index_0(&self) -> u64 {
Expand Down
14 changes: 14 additions & 0 deletions tests/preserve-encodings/input.cddl
Original file line number Diff line number Diff line change
Expand Up @@ -90,11 +90,25 @@ array_opt_fields = [
; ? z: null,
]

hash = bytes .size (0..8)

bounds = [
w: -1000 .. 1000
x: uint .le 7,
y: nint .ge -5,
z: text .size (3..14),
a: [* uint] .size (1..3),
b: { * uint => uint } .le 3
]

bounds_type_choice = bytes .size (0..64)
/ text .size (0..64)

bounds_group_choice = [
; @name a
a: uint, b: text .le 4 //
; @name b
hash //
; @name c
1, x: hash, y: hash
]
7 changes: 7 additions & 0 deletions tests/preserve-encodings/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -791,6 +791,13 @@ mod tests {
assert!(make_bounds(OOB::Lower, OOB::Upper, OOB::Lower, OOB::Upper, OOB::Above, OOB::Upper).is_err());
// b oob
assert!(make_bounds(OOB::Lower, OOB::Upper, OOB::Lower, OOB::Upper, OOB::Upper, OOB::Above).is_err());

// type and group choices share the same deserialization code so we only check the API
assert!(BoundsTypeChoice::new_bytes(vec![0; 64]).is_ok());
assert!(BoundsTypeChoice::new_bytes(vec![0; 65]).is_err());
assert!(BoundsGroupChoice::new_a(0, "four".to_owned()).is_ok());
assert!(BoundsGroupChoice::new_a(0, "hello".to_owned()).is_err());
deser_test(&BoundsGroupChoice::new_c(Hash::new(vec![]).unwrap(), Hash::new(vec![]).unwrap()));
}

#[test]
Expand Down

0 comments on commit 45071ae

Please sign in to comment.