Skip to content

Commit

Permalink
Fixed bounds checking for assocaited discriminants.
Browse files Browse the repository at this point in the history
  • Loading branch information
InsertCreativityHere committed Dec 13, 2023
1 parent 7c7b689 commit 9780341
Show file tree
Hide file tree
Showing 2 changed files with 57 additions and 7 deletions.
15 changes: 8 additions & 7 deletions src/validators/enums.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,8 @@ fn backing_type_bounds(enum_def: &Enum, diagnostics: &mut Diagnostics) {
}
} else {
// Enum was defined in a Slice2 file.
// Non-integrals are handled by `allowed_underlying_types`
fn check_bounds(enum_def: &Enum, underlying_type: &Primitive, diagnostics: &mut Diagnostics) {
let (min, max) = underlying_type.numeric_bounds().unwrap();

fn check_bounds(enum_def: &Enum, (min, max): (i128, i128), diagnostics: &mut Diagnostics) {
enum_def
.enumerators()
.iter()
Expand All @@ -60,13 +59,15 @@ fn backing_type_bounds(enum_def: &Enum, diagnostics: &mut Diagnostics) {
}
match &enum_def.underlying {
Some(underlying_type) => {
if underlying_type.is_integral() {
check_bounds(enum_def, underlying_type, diagnostics);
// Non-integral underlying types are rejected by the `allowed_underlying_types` check.
if let Some(bounds) = underlying_type.numeric_bounds() {
check_bounds(enum_def, bounds, diagnostics);
}
}
None => {
// No underlying type, the default is varint32 for Slice2.
check_bounds(enum_def, &Primitive::VarInt32, diagnostics);
// For enumerators in Slice2, values must fit within varint32 and be positive.
let varint32_max = Primitive::VarInt32.numeric_bounds().unwrap().1;
check_bounds(enum_def, (0, varint32_max), diagnostics);
}
}
}
Expand Down
49 changes: 49 additions & 0 deletions tests/enums/container.rs
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,55 @@ mod associated_fields {
assert_eq!(enumerator_d.value(), 4);
}

#[test]
fn explicit_values_must_be_within_range() {
// Arrange
let slice = "
module Test
enum E {
ImplicitOkay // 0
ExplicitNegative = -3 // -3
ImplicitNegative(tag(4) s: string?) // -2
Okay(b: bool) = 2_147_483_647 // 2_147_483_647
ImplicitOverflow // 2_147_483_648
ExplicitOverflow = 0x686921203A7629 // something big
ExplicitOkay(a: int8) = 79 // 79
}
";

// Act
let diagnostics = parse_for_diagnostics(slice);

// Arrange
let expected = [
Diagnostic::new(Error::EnumeratorValueOutOfBounds {
enumerator_identifier: "ExplicitNegative".to_owned(),
value: -3,
min: 0,
max: i32::MAX as i128,
}),
Diagnostic::new(Error::EnumeratorValueOutOfBounds {
enumerator_identifier: "ImplicitNegative".to_owned(),
value: -2,
min: 0,
max: i32::MAX as i128,
}),
Diagnostic::new(Error::EnumeratorValueOutOfBounds {
enumerator_identifier: "ImplicitOverflow".to_owned(),
value: 2_147_483_648,
min: 0,
max: i32::MAX as i128,
}),
Diagnostic::new(Error::EnumeratorValueOutOfBounds {
enumerator_identifier: "ExplicitOverflow".to_owned(),
value: 0x686921203A7629,
min: 0,
max: i32::MAX as i128,
}),
];
check_diagnostics(diagnostics, expected);
}

#[test]
fn associated_fields_are_scoped_correctly() {
// Arrange
Expand Down

0 comments on commit 9780341

Please sign in to comment.