Skip to content

Commit

Permalink
OER: fix untagged sequence bitfield bits (#279)
Browse files Browse the repository at this point in the history
  • Loading branch information
Nicceboy authored Jun 25, 2024
1 parent a759bff commit 413a39a
Show file tree
Hide file tree
Showing 2 changed files with 65 additions and 8 deletions.
21 changes: 21 additions & 0 deletions src/coer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1242,4 +1242,25 @@ mod tests {
&[192, 3, 0, 1, 2, 2, 7, 128, 0]
);
}
#[test]
// https://github.com/librasn/rasn/issues/271
fn test_untagged_duplicate_type_option_on_sequence() {
use crate as rasn;
#[derive(AsnType, Decode, Encode, Clone, Debug, PartialEq, Eq)]
pub struct SequenceOptionals {
pub it: Integer,
pub is: Option<OctetString>,
pub late: Option<Integer>,
}
round_trip!(
coer,
SequenceOptionals,
SequenceOptionals {
it: 1.into(),
is: Some(OctetString::from_static(&[0x01, 0x02, 0x03])),
late: None
},
&[0b10000000, 0x01, 0x01, 0x03, 0x01, 0x02, 0x03]
);
}
}
52 changes: 44 additions & 8 deletions src/oer/enc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,9 @@ pub struct Encoder {
options: EncoderOptions,
output: Vec<u8>,
set_output: alloc::collections::BTreeMap<Tag, Vec<u8>>,
field_bitfield: alloc::collections::BTreeMap<Tag, (FieldPresence, bool)>,
// usize a.k.a. field index defines the order for Sequence
field_bitfield: alloc::collections::BTreeMap<(usize, Tag), (FieldPresence, bool)>,
current_field_index: usize,
extension_fields: Vec<Option<Vec<u8>>>,
is_extension_sequence: bool,
parent_output_length: Option<usize>,
Expand Down Expand Up @@ -110,6 +112,7 @@ impl Encoder {
output: <_>::default(),
set_output: <_>::default(),
field_bitfield: <_>::default(),
current_field_index: <_>::default(),
extension_fields: <_>::default(),
is_extension_sequence: bool::default(),
parent_output_length: <_>::default(),
Expand All @@ -133,7 +136,23 @@ impl Encoder {
.unwrap_or(self.output)
}
pub fn set_bit(&mut self, tag: Tag, bit: bool) {
self.field_bitfield.entry(tag).and_modify(|(_, b)| *b = bit);
// In set encoding, field index does not matter
// Tags need to be unique
if self.options.set_encoding {
self.field_bitfield
.entry((usize::default(), tag))
.and_modify(|(_, b)| *b = bit);
} else {
match self.field_bitfield.entry((self.current_field_index, tag)) {
alloc::collections::btree_map::Entry::Occupied(mut occupied) => {
occupied.get_mut().1 = bit;
self.current_field_index += 1;
}
alloc::collections::btree_map::Entry::Vacant(_) => {
// Key does not exist, do nothing
}
}
}
}
fn extend(&mut self, tag: Tag, bytes: Vec<u8>) -> Result<(), EncodeError> {
match self.output.len().checked_add(bytes.len()) {
Expand Down Expand Up @@ -435,7 +454,12 @@ impl Encoder {
encoder.field_bitfield = C::FIELDS
.canonised()
.iter()
.map(|field| (field.tag_tree.smallest_tag(), (field.presence, false)))
.map(|field| {
(
(usize::default(), field.tag_tree.smallest_tag()),
(field.presence, false),
)
})
.collect();
encoder.parent_output_length = Some(self.output_length());
encoder
Expand All @@ -445,7 +469,8 @@ impl Encoder {
let mut encoder = Self::new(self.options.without_set_encoding());
encoder.field_bitfield = C::FIELDS
.iter()
.map(|field| (field.tag_tree.smallest_tag(), (field.presence, false)))
.enumerate()
.map(|(i, field)| ((i, field.tag_tree.smallest_tag()), (field.presence, false)))
.collect();
encoder.parent_output_length = Some(self.output_length());
encoder
Expand Down Expand Up @@ -808,9 +833,12 @@ impl crate::Encoder for Encoder {
tag: Tag,
value: &V,
) -> Result<Self::Ok, Self::Error> {
if let Some((_, true)) = self.field_bitfield.get(&tag) {
if let Some((_, true)) = self.field_bitfield.get(&(self.current_field_index, tag)) {
value.encode(self)
} else if !self.field_bitfield.contains_key(&tag) {
} else if !self
.field_bitfield
.contains_key(&(self.current_field_index, tag))
{
value.encode(self)
} else {
self.set_bit(tag, true);
Expand Down Expand Up @@ -920,9 +948,17 @@ impl crate::Encoder for Encoder {
value: E,
) -> Result<Self::Ok, Self::Error> {
let mut encoder = Self::new(self.options.without_set_encoding());
encoder.field_bitfield = <_>::from([(tag, (FieldPresence::Optional, false))]);
encoder.current_field_index = self.current_field_index;
encoder.field_bitfield = <_>::from([(
(self.current_field_index, tag),
(FieldPresence::Optional, false),
)]);
E::encode_with_tag_and_constraints(&value, &mut encoder, tag, constraints)?;
if encoder.field_bitfield.get(&tag).map_or(false, |(_, b)| *b) {
if encoder
.field_bitfield
.get(&(self.current_field_index, tag))
.map_or(false, |(_, b)| *b)
{
self.set_bit(tag, true);
self.extension_fields.push(Some(encoder.output()));
} else {
Expand Down

0 comments on commit 413a39a

Please sign in to comment.