Skip to content

Commit a1eddeb

Browse files
committed
Deny invalid bits which are out of range
1 parent 4b4a504 commit a1eddeb

File tree

6 files changed

+57
-6
lines changed

6 files changed

+57
-6
lines changed

bitbybit/src/bitfield/parsing.rs

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -378,11 +378,11 @@ fn parse_field(base_data_size: usize, field: &Field) -> Result<FieldDefinition>
378378
(indexed_count - 1) * indexed_stride.unwrap() + highest_bit_index_in_ranges;
379379
if number_of_bits_indexed > base_data_size {
380380
return Err(Error::new_spanned(
381-
field.attrs.first(),
382-
format!(
383-
"bitfield!: Array-field {} requires {number_of_bits_indexed} bits for the array, but only has ({})", field_name, base_data_size
384-
)
385-
));
381+
field.attrs.first(),
382+
format!(
383+
"bitfield!: Array-field {} requires {number_of_bits_indexed} bits for the array, but only has ({})", field_name, base_data_size
384+
)
385+
));
386386
}
387387

388388
if indexed_count < 2 {
@@ -396,6 +396,8 @@ fn parse_field(base_data_size: usize, field: &Field) -> Result<FieldDefinition>
396396
}
397397
}
398398

399+
verify_bits_in_range(field, field_name, &ranges, base_data_size)?;
400+
399401
let (custom_type, getter_type, setter_type) = if field_type_size_from_data_type.is_none() {
400402
parse_enumeration(ty, &primitive_type)?
401403
} else {
@@ -430,11 +432,30 @@ fn parse_field(base_data_size: usize, field: &Field) -> Result<FieldDefinition>
430432
doc_comment,
431433
array: indexed_count.map(|count| (count, indexed_stride.unwrap())),
432434
field_type_size_from_data_type: field_type_size_from_data_type.map(|v| v.0),
433-
is_signed: field_type_size_from_data_type.map_or(false, |v| v.1),
435+
is_signed: field_type_size_from_data_type.is_some_and(|v| v.1),
434436
unsigned_field_type,
435437
})
436438
}
437439

440+
fn verify_bits_in_range(
441+
field: &Field,
442+
field_name: &Ident,
443+
ranges: &[Range<usize>],
444+
base_data_size: usize,
445+
) -> syn::Result<()> {
446+
let highest_bit_index_in_ranges = ranges.iter().map(|range| range.end).max().unwrap_or(0);
447+
if highest_bit_index_in_ranges > base_data_size {
448+
return Err(Error::new_spanned(
449+
field.attrs.first(),
450+
format!(
451+
"bitfield!: Field {} requires {} bits, but only has ({})",
452+
field_name, highest_bit_index_in_ranges, base_data_size
453+
),
454+
));
455+
}
456+
Ok(())
457+
}
458+
438459
/// Parses the arguments of a field. At the beginning and after each comma, Reset is used. After
439460
/// that, the various take_xxx functions are used to switch states.
440461
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
use bitbybit::bitfield;
2+
3+
#[bitfield(u32, default = 0)]
4+
struct Test {
5+
#[bit(32, rw)]
6+
field: bool,
7+
}
8+
9+
fn main() {}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
error: bitfield!: Field field requires 33 bits, but only has (32)
2+
--> tests/no_compile/invalid_bit_pos.rs:5:5
3+
|
4+
5 | #[bit(32, rw)]
5+
| ^^^^^^^^^^^^^^
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
use bitbybit::bitfield;
2+
3+
#[bitfield(u32, default = 0)]
4+
struct Test {
5+
#[bits(31..=32, rw)]
6+
field: u2,
7+
}
8+
9+
fn main() {}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
error: bitfield!: Field field requires 33 bits, but only has (32)
2+
--> tests/no_compile/invalid_bits_pos.rs:5:5
3+
|
4+
5 | #[bits(31..=32, rw)]
5+
| ^^^^^^^^^^^^^^^^^^^^

bitbybit/tests/tests.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,4 +10,6 @@ fn all_tests() {
1010
t.compile_fail("tests/no_compile/non_exhaustive_bitenum.rs");
1111
t.compile_fail("tests/no_compile/invalid_field_range.rs");
1212
t.compile_fail("tests/no_compile/invalid_field_access.rs");
13+
t.compile_fail("tests/no_compile/invalid_bit_pos.rs");
14+
t.compile_fail("tests/no_compile/invalid_bits_pos.rs");
1315
}

0 commit comments

Comments
 (0)