Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Combination of optional fields and explicit tag ignores the option type #272

Open
Nicceboy opened this issue Jun 20, 2024 · 3 comments
Open

Comments

@Nicceboy
Copy link
Contributor

Nicceboy commented Jun 20, 2024

When explicit tags are used for optional fields, wrong decoding (maybe encoding too) functions are derived. Or maybe option type disappears somehow, as the code does not hit the decode_optional_* methods.

This seemed to be rather hard to debug, if there are any hints where this check happens.

use rasn::{oer, prelude::*};

#[derive(AsnType, Decode, Encode, Clone, Debug, PartialEq, Eq)]
pub struct SequenceOptionals {
    #[rasn(tag(explicit(0)))]
    pub it: Integer,
    #[rasn(tag(explicit(1)))]
    pub is: Option<OctetString>,
    #[rasn(tag(explicit(2)))]
    pub late: Option<Integer>,
}
fn main() {
    let test_seq = SequenceOptionals {
        it: 42.into(),
        is: None,
        late: None,
    };
    let encoded = oer::encode(&test_seq).unwrap();
    dbg!(&encoded);
    let decoded: SequenceOptionals = oer::decode(&encoded).unwrap();
    dbg!(&decoded);
    assert_eq!(test_seq, decoded);
}

Output (decoder does not hit the decode_option_*

[testing/src/main.rs:19:5] &encoded = [
    0,
    1,
    42,
]
[testing/src/main.rs:21:5] &decoded = SequenceOptionals {
    it: 42,
    is: Some(
        b"",
    ),
    late: None,
}
thread 'main' panicked at testing/src/main.rs:22:5:
assertion `left == right` failed
  left: SequenceOptionals { it: 42, is: None, late: None }
 right: SequenceOptionals { it: 42, is: Some(b""), late: None }
stack backtrace:
   0: rust_begin_unwind
             at /rustc/ada5e2c7b5427a591e30baeeee2698a5eb6db0bd/library/std/src/panicking.rs:652:5
   1: core::panicking::panic_fmt
             at /rustc/ada5e2c7b5427a591e30baeeee2698a5eb6db0bd/library/core/src/panicking.rs:72:14
   2: core::panicking::assert_failed_inner
   3: core::panicking::assert_failed
             at /rustc/ada5e2c7b5427a591e30baeeee2698a5eb6db0bd/library/core/src/panicking.rs:363:5
   4: testing::main
             at ./src/main.rs:22:5
   5: core::ops::function::FnOnce::call_once
             at /rustc/ada5e2c7b5427a591e30baeeee2698a5eb6db0bd/library/core/src/ops/function.rs:250:5
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.

With tag() it works fine and correct code is executed.

@Nicceboy
Copy link
Contributor Author

Seems like that current option values are based on mapping the Result to Option, so Option value is not really based on the decoder logic:

impl rasn::Decode for SequenceOptionals {
    fn decode_with_tag_and_constraints<'constraints, D: rasn::Decoder>(
        decoder: &mut D,
        tag: rasn::Tag,
        constraints: rasn::types::Constraints<'constraints>,
    ) -> core::result::Result<Self, D::Error> {
        decoder.decode_sequence(tag, None::<fn() -> Self>, |decoder| {
            Ok(Self {
                it: {
                    decoder
                        .decode_explicit_prefix(rasn::Tag::new(rasn::types::Class::Context, 0))
                        .map_err(|error| {
                            rasn::de::Error::field_error(
                                "SequenceOptionals.it",
                                error.into(),
                                decoder.codec(),
                            )
                        })?
                },
                is: {
                    decoder
                        .decode_explicit_prefix(rasn::Tag::new(rasn::types::Class::Context, 1))
                        .ok()
                },
                late: {
                    decoder
                        .decode_explicit_prefix(rasn::Tag::new(rasn::types::Class::Context, 2))
                        .ok()
                },
            })
        })
    }
}

@Nicceboy
Copy link
Contributor Author

Seems like there is also bug in OER. When resolved, it which fixes this particular case, but I am not sure if this is still issue on some other scenarios.

@XAMPPRocky
Copy link
Collaborator

We can probably remove the ok and/or add an explicit type parameter to decode explicit prefix.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants