kellerkindt / asn1rs

Generates Rust Code and optionally compatible Protobuf schema files from ASN.1 definitions.
http://asn1.rs
Apache License 2.0
54 stars 19 forks source link

Extensible SEQUENCE causes errors during serialization #80

Closed awm129 closed 1 year ago

awm129 commented 1 year ago

Compiling the following asn1 which defines an extensible SEQUENCE:

TestTypes DEFINITIONS AUTOMATIC TAGS ::= BEGIN                                                                                                                                                                                                                                                                                                                                                                                                                                                                     
  MySequence ::= SEQUENCE {                                                                                                                                                                                                                                    
    val1 INTEGER,                                                                                                                                                                                                                                              
    val2 INTEGER,                                                                                                                                                                                                                                              
    ...                                                                                                                                                                                                                                                        
  }                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                
END

with asn1rs works (also compiles with asn1c), however, when using the generated rust bindings, it panics in asn1rs source. For example, using the above definition in a serialization test like so:

extern crate asn1rs_test;                                                                                                                                                                                                                                    
extern crate asn1rs;                                                                                                                                                                                                                                           

use asn1rs_test::test_types::*;                                                                                                                                                                                                                              
use asn1rs::prelude::*;                                                                                                                                                                                                                                        

fn main()                                                                                                                                                                                                                                                      
{                                                                                                                                                                                                                                                              
    let my_sequence = MySequence{[ ]                                                                                                                                                                                                                           
        val1: 1020,                                                                                                                                                                                                                                            
        val2: 1080                                                                                                                                                                                                                                             
    };                                                                                                                                                                                                                                                         

    let mut writer = UperWriter::default();                                                                                                                                                                                                                    
    writer.write(&my_sequence).unwrap();                                                                                                                                                                                                                       
    let mut reader = writer.as_reader();                                                                                                                                                                                                                       
    let deser = reader.read::<MySequence>().unwrap();                                                                                                                                                                                                          
    assert_eq!(my_sequence, deser);                                                                                                                                                                                                                            
}

Fails with

---- serde_mysequence stdout ----
thread 'main' panicked at 'assertion failed: scope.unwrap().exhausted()', /home/user/.cargo/registry/src/index.crates.io-6f17d22bba15001f/asn1rs-0.2.2/src/syn/io/uper.rs:224:9
kellerkindt commented 1 year ago

Thanks for raising the issue. As you can see in the commit 972cb4a, I added your scenario to the test-suite (here is the result), but it does not fail as you mentioned (or at all). Could you describe in more detail, what you mean 'with serde', because asn1rs always depends on serde atm.

awm129 commented 1 year ago

Thanks for looking into this! Your test does seem to be working and tests pass on that branch if I run it locally as well. Apologies for the confusion around my 'with serde' comment, I should have been more general and re-phrased this "during serialization" (I updated the issue title and my initial comment accordingly).

However, I'm still seeing this fail if I run something similar outside of asn1rs's test suite:

protocol_test:~ $ ls                                                                                                                                                                                                                                            
Cargo.toml  src                                                                                                                                                                                                                                    
protocol_test:~ $ ls src/                                                                                                                                                                                                                                       
main.rs  test_types.asn1                                                                                                                                                                                                                                       
protocol_test:~ $ asn1rs --version                                                                                                                                                                                                                              
asn1rs 0.2.2                                                                                                                                                                                                                                                   
protocol_test:~ $ asn1rs src/ src/test_types.asn1                                                                                                                                                                                                               
Successfully converted TestTypes => test_types.rs                                                                                                                                                                                                              
protocol_test:~ $ ls src/                                                                                                                                                                                                                                       
main.rs  test_types.asn1  test_types.rs                                                                                                                                                                                                                        
protocol_test:~ $ RUST_BACKTRACE=1 cargo run                                                                                                                                                                                                                    
   Compiling proc-macro2 v1.0.66                                                                                                                                                                                                                               
  ...<snip>...
   Compiling asn1rs-model v0.2.2
   Compiling asn1rs-macros v0.2.2
   Compiling asn1rs v0.2.2                                     
   Compiling protocol_test v0.1.0 (/home/user/src/protocol_test)
warning: associated functions `val1_min`, `val1_max`, `val2_min`, and `val2_max` are never used
  --> src/test_types.rs:12:18
     |
11 | impl MySequence {
   | --------------- associated functions in this implementation
12 |     pub const fn val1_min() -> u64 {
   |                  ^^^^^^^^
...
16 |     pub const fn val1_max() -> u64 {
   |                  ^^^^^^^^
...
20 |     pub const fn val2_min() -> u64 {
   |                  ^^^^^^^^
...
24 |     pub const fn val2_max() -> u64 {
   |                  ^^^^^^^^
   |
   = note: `#[warn(dead_code)]` on by default

warning: `protocol_test` (bin "protocol_test") generated 1 warning
    Finished dev [unoptimized + debuginfo] target(s) in 12.73s
     Running `target/debug/protocol_test`
thread 'main' panicked at 'assertion failed: scope.unwrap().exhausted()', /home/user/.cargo/registry/src/index.crates.io-6f17d22bba15001f/asn1rs-0.2.2/src/syn/io/uper.rs:224:9
stack backtrace:
   0: rust_begin_unwind
             at /rustc/90c541806f23a127002de5b4038be731ba1458ca/library/std/src/panicking.rs:578:5
   1: core::panicking::panic_fmt
             at /rustc/90c541806f23a127002de5b4038be731ba1458ca/library/core/src/panicking.rs:67:14
   2: core::panicking::panic
             at /rustc/90c541806f23a127002de5b4038be731ba1458ca/library/core/src/panicking.rs:117:5
   3: asn1rs::syn::io::uper::UperWriter::scope_pushed
             at /home/user/.cargo/registry/src/index.crates.io-6f17d22bba15001f/asn1rs-0.2.2/src/syn/io/uper.rs:224:9
   4: <asn1rs::syn::io::uper::UperWriter as asn1rs::syn::Writer>::write_sequence::{{closure}}
             at /home/user/.cargo/registry/src/index.crates.io-6f17d22bba15001f/asn1rs-0.2.2/src/syn/io/uper.rs:324:17
   5: asn1rs::syn::io::uper::UperWriter::with_buffer
             at /home/user/.cargo/registry/src/index.crates.io-6f17d22bba15001f/asn1rs-0.2.2/src/syn/io/uper.rs:260:13
   6: <asn1rs::syn::io::uper::UperWriter as asn1rs::syn::Writer>::write_sequence
             at /home/user/.cargo/registry/src/index.crates.io-6f17d22bba15001f/asn1rs-0.2.2/src/syn/io/uper.rs:304:9
   7: <asn1rs::syn::sequence::Sequence<C> as asn1rs::syn::WritableType>::write_value
             at /home/user/.cargo/registry/src/index.crates.io-6f17d22bba15001f/asn1rs-0.2.2/src/syn/sequence.rs:27:9
   8: <protocol_test::test_types::MySequence as asn1rs::syn::Writable>::write
             at ./src/test_types.rs:3:1
   9: asn1rs::syn::Writer::write
             at /home/user/.cargo/registry/src/index.crates.io-6f17d22bba15001f/asn1rs-0.2.2/src/syn/mod.rs:150:9
  10: protocol_test::main
             at ./src/main.rs:14:5
  11: core::ops::function::FnOnce::call_once
             at /rustc/90c541806f23a127002de5b4038be731ba1458ca/library/core/src/ops/function.rs:250:5
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.
protocol_test:~ $ 

In the above shell sequence, I'm using the command line version of asn1rs to compile an ASN1 definition into a rust source file to produce rust bindings for my MySequence ASN1 SEQUENCE. I am then referencing and using that source file in my project. Perhaps I'm doing something wrong?

For completeness, the source files I'm using are very similar to what I posted earlier and you used in 972cb4a:

test_types.asn1

TestTypes DEFINITIONS AUTOMATIC TAGS ::= BEGIN
  MySequence ::= SEQUENCE {
    val1 INTEGER,
    val2 INTEGER,
    ...
  }
END

main.rs

mod test_types;
use asn1rs::prelude::*;

fn main()
{
    let my_sequence = test_types::MySequence{
        val1: 1020,
        val2: 1080
    };

    let mut writer = UperWriter::default();
    writer.write(&my_sequence).unwrap();
    let mut reader = writer.as_reader();
    let deser = reader.read::<test_types::MySequence>().unwrap();
    assert_eq!(my_sequence, deser);
}

If I remove the extensibility indicator (line 5) from test_types.asn1, the above sequence of shell commands seems to work just fine.

kellerkindt commented 1 year ago

Hmm, my guess is that one of the fixes since the release of v0.2.2 (which is already 2 years old ... o.o) fixed the problem you describe here as well.

Would you mind trying again with a bleeding edge version? Try updating your Cargo.toml like this:

asn1rs = { git = "https://github.com/kellerkindt/asn1rs.git", rev = "b6baff2" }

... I guess, I should then publish a new version to crates.io soon-ish...

EDIT: And if that does not resolve the issue, would you mind pasting the error with the feature descriptive-deserialize-errors enabled?

awm129 commented 1 year ago

That worked!

Thanks so much for your help! asn1rs has been really helpful for me and I'll look forward to an update on crates.io soon.

kellerkindt commented 1 year ago

Great that this did the trick! I also published a new version to crates-io: v0.3.1