Samuel-Tyler / fast_ber

A C++11 ASN.1 BER Encoding and Decoding Library
Boost Software License 1.0
84 stars 11 forks source link

Add support for types with default values #9

Open Samuel-Tyler opened 4 years ago

Samuel-Tyler commented 4 years ago

Add support for default values. Check encoding rules for BER and DER when value is sentinel.

jbulow commented 4 years ago

The parser accepts default values if they are in the end of a declaration. Otherwise there will be a syntax error:

SomeSeq ::= SEQUENCE
{
  flag1          BOOLEAN DEFAULT FALSE,
  seq1     SEQUENCE OF seqItem,
...
}

results in:

syntax error, unexpected SEQUENCE, expecting }

on the seq1 line.

Samuel-Tyler commented 4 years ago

This seems to work for me on master head / devel.

styler@styler:~/git/fast_ber/build$ cat ../testfiles/defaults.asn
Defaults

DEFINITIONS EXPLICIT TAGS ::=

BEGIN

SeqItem ::= INTEGER
SomeSeq ::= SEQUENCE
{
  flag1          BOOLEAN DEFAULT FALSE,
  seq1     SEQUENCE OF SeqItem,
...
}

END
styler@styler:~/git/fast_ber/build$ ./src/fast_ber_compiler ../testfiles/defaults.asn a
styler@styler:~/git/fast_ber/build$ echo $?
0
jbulow commented 4 years ago

Now I get error on

someSeq ::= SEQUENCE
{
  someInt1   INTEGER,
  flag1 BOOLEAN DEFAULT FALSE,
  someInt 2  INTEGER OPTIONAL  -- error on this one
}
test.asn1:365:19-26: syntax error, unexpected INTEGER, expecting }
Samuel-Tyler commented 4 years ago

Do you have a space after someInt?

jbulow commented 4 years ago

No, that was only a typo when I entered the defect. Sorry

Samuel-Tyler commented 4 years ago

Seems to work ok

SomeSeq ::= SEQUENCE
{
  someInt1   INTEGER,
  flag1 BOOLEAN DEFAULT FALSE,
  someInt2  INTEGER OPTIONAL  -- error on this one
}

END
styler@styler:~/git/fast_ber/build$ ./src/fast_ber_compiler ../testfiles/defaults.asn  a
styler@styler:~/git/fast_ber/build$ echo $?
0
kurkpitaine commented 4 years ago

Default value does not work on curly braced values. Using packaged random_test_spec.asn file, compiler pops an error on line 82:

Next token is token DEFAULT (random_test_spec.asn:82.36-42: )
Shifting token DEFAULT (random_test_spec.asn:82.36-42: )
Entering state 452
Reading a token: Next token is token "{" (random_test_spec.asn:82.45: )
random_test_spec.asn:82.45syntax error, unexpected {

This error is related to this sequence, particularly the version BIT STRING:

Return-of-sales ::= SEQUENCE
 {version BIT STRING
 {version1 (0), version2 (1)} DEFAULT {version1},
 no-of-days-reported-on INTEGER
 {week(7), month (28), maximum (56)} (1..56) DEFAULT week,
 time-and-date-of-report CHOICE
 {two-digit-year UTCTime,
 four-digit-year GeneralizedTime},
 -- If the system clock provides a four-digit year,
 -- the second alternative shall be used. With the
 -- first alternative the time shall be interpreted
 -- as a sliding window.
 reason-for-delay ENUMERATED
 {computer-failure, network-failure, other} OPTIONAL,
 -- Include this field if and only if the
 -- no-of-days-reported-on exceeds seven.
 additional-information SEQUENCE OF PrintableString OPTIONAL,
 -- Include this field if and only if the
 -- reason-for-delay is "other".
 sales-data SET OF Report-item,
 ... }

Removing the curly braces from the definition, the compiler does not complain about an unexpected '{' but it does not find 'version1':

Compilation error: Reference to undefined type: version1
Samuel-Tyler commented 4 years ago

Thank you, I will take a look. Parsing value types in ASN.1 is very difficult due to ambiguities in the specification.

kurkpitaine commented 4 years ago

I dig a bit for the curly braces, defining ComponentType in the grammar like below corrects the curly braces issue:

ComponentType:
    Type
    { std::cerr << context.location << " WARNING: unnamed type\n";
      $$ = ComponentType{{gen_anon_member_name(), $1}, false, absl::nullopt, absl::nullopt, StorageMode::static_ }; }
|   Type OPTIONAL
    { std::cerr << context.location << " WARNING: unnamed type\n";
      $$ = ComponentType{{gen_anon_member_name(), $1}, true, absl::nullopt, absl::nullopt, StorageMode::static_ }; }
|   Type DEFAULT SingleValue
    { $$ = ComponentType{{gen_anon_member_name(), $1}, false, $3, absl::nullopt, StorageMode::static_ };
      std::cerr << context.location << " WARNING: unnamed type\n"; }
|   Type DEFAULT "{" SingleValue "}"
    { $$ = ComponentType{{gen_anon_member_name(), $1}, false, $4, absl::nullopt, StorageMode::static_ };
      std::cerr << context.location << " WARNING: unnamed type\n"; }
|   NamedType
    { $$ = ComponentType{$1, false, absl::nullopt, absl::nullopt, StorageMode::static_ }; }
|   NamedType OPTIONAL
    { $$ = ComponentType{$1, true, absl::nullopt, absl::nullopt, StorageMode::static_ }; }
|   NamedType DEFAULT SingleValue
    { $$ = ComponentType{$1, false, $3, absl::nullopt, StorageMode::static_ }; }
|   NamedType DEFAULT "{" SingleValue "}"
    { $$ = ComponentType{$1, false, $4, absl::nullopt, StorageMode::static_ }; }
|   COMPONENTS OF Type
    { $$ = ComponentType{{}, false, absl::nullopt, $3, StorageMode::static_}; }
Samuel-Tyler commented 4 years ago

That will fix this particular issue, and that's fine. Perhaps adding a ValueList type ({SingleValue, SingleValue, SingleValue...})will help more generally. Ideally this should be the type Value, although that may cause other things to break.

For the other issue, NamedBitLists are not yet supported at all. I'll work on that now.

BitStringType:
    BIT STRING
    { $$ = BitStringType{}; }
|   BIT STRING "{" NamedBitList "}"
    { $$ = BitStringType{}; }