Unable to decode or encode Asn1 messages```

Hi,

I have the issue, that when I try to encode a message with the following Asn1 message (this is only an excerpt of a bigger message), I get a MatchError.

Encoding and decoding the Text sequence works, but as soon as I try to decode the TextLines sequence it breaks.

TextLines ::= SEQUENCE (SIZE (1..4),...) OF Text

Text ::= SEQUENCE {
layoutComponentId	INTEGER(1..4,...) OPTIONAL,
language			BIT STRING (SIZE (10)),
textContent			UTF8String
}

A Jer Representation of a message, that does not work, is the following.

	{
		"layoutComponentId": 2,
		"language": "36C0",
		"textContent": "test 1"
	},
	{
		"layoutComponentId": 4,
		"language": "1540",
		"textContent": "test 2"
	},
	{
		"language": "B340",
		"textContent": "test 3"
	}
]

Also, when I decode the jer message and encode it using the asn1 library, those messages cannot be decoded with other decoders.

The other decoder/encoder that is used is from OSS Nokalva.

Can someone help me with this issue?

Thanks
stefan

I don’t know if I can help you here but some quick questions:
How do you mean breaks down?
And can you give an example of the data you were trying to match and the pattern you were trying to match against?

can you take the JSON representation you showed and decode and show us the resulting Erlang term. Then encode that Erlang term as Textlines and show the resulting JSON.

Assuming that the original representation is a valid Json according to JER, and that the OSS Nokalva can decode it there must be some difference in the Json from the Erlang encoder and the original.

First of all, thanks for the reply,

I guess I missed some relevant information in my initial question.

The .erl module is created with the following command.

erlc -buper +jer +maps +noobj -I ./asn1 -o ./src ./asn1/FailingTextContainer.asn

The encoding rule I need to en/decode is UPER. The Json representation is only used for debugging purpose.

When decoding the Json representation, from the initial post, using the jer_decode/2 function, and then encoding it using enc_TextLines/1 the resulting output is

[
  3,
  [
    <<1::size(1)>>,
    <<1::size(3)>>,
    <<54, 3::size(2)>>,
    6 |
    "test 1"
  ],
  [
    <<1::size(1)>>,
    <<3::size(3)>>,
    <<21, 1::size(2)>>,
    6 |
    "test 2"
  ],
  [<<0::size(1)>>, [], <<179, 1::size(2)>>, 6 | "test 3"]
]

After converting it to bytes, it looks like this and can again be decoded using dec_TextLines/1.

<<3, 147, 108, 25, 209, 149, 205, 208, 128, 198, 197, 80, 103,
  70, 87, 55, 66, 3, 37, 154, 12, 232, 202, 230, 232, 64, 102>>

The UPER message from the OSS Nokalva encoder on the other hand looks is the following.

<<82, 109, 131, 58, 50, 185, 186, 16, 24, 216, 170, 12, 232, 202,
  230, 232, 64, 100, 179, 65, 157, 25, 92, 221, 8, 12, 192>>

When this is decoded using dec_TextLines/1, I get

** (MatchError) no match of right hand side value: <<209, 149, 205, 208, 128, 198, 197, 80, 103, 70, 87, 55, 66, 3, 37, 154, 12, 232, 202, 230, 232, 64, 102, 0::size(5)>>
    (asn12proto3 0.1.0) src/FailingTextContainer.erl:252: :FailingTextContainer.dec_Text/1
    (asn12proto3 0.1.0) src/FailingTextContainer.erl:355: :FailingTextContainer.dec_fragment2/3
    (asn12proto3 0.1.0) src/FailingTextContainer.erl:345: :FailingTextContainer.dec_components1/2

To me, it seems, like the issue might be caused by the extension of the constraint, since the dec_components1/2 looks within the .erl module looks like this

dec_components1(Bytes, Acc) ->
    %% Length with constraint no
    {V1@V0, V1@Buf1} =
        case Bytes of
            <<0:1, V1@V3:7, V1@Buf4/bitstring>> -> %% the size for the constraint takes 7 bit.
                {V1@V3, V1@Buf4};
            <<1:1, 0:1, V1@V4:14, V1@Buf5/bitstring>> ->
                {V1@V4, V1@Buf5};
            <<1:1, 1:1, V1@V4:6, V1@Buf5/bitstring>> ->
                V1@Mul6 = V1@V4 * 16384,
                {V1@Mul6, V1@Buf5}
        end,
    {Acc1, Buf1} = dec_fragment2(V1@V0, V1@Buf1, Acc),
    if
        V1@V0 >= 16384 ->
            dec_components1(Buf1, Acc1);
        true ->
            {lists:reverse(Acc1), Buf1}
    end.

When I replace the <<0:1, V1@V3:7, V1@Buf4/bitstring>> -> with <<0:1, V1@V3:2, V1@Buf4/bitstring>> -> and add one (as the minimum value is 1, not 0) to the V1@V0 variable, the decoding is working and is generating the following term

{[
   %{language: <<54, 3::size(2)>>, layoutComponentId: 2, textContent: "test 1"},
   %{language: <<21, 1::size(2)>>, layoutComponentId: 4, textContent: "test 2"},
   %{language: <<179, 1::size(2)>>, textContent: "test 3"}
 ], <<0::size(6)>>}

Unfortunately, this modification, is it only addresses a single case of messages.

I hope this clarifies my issue a little, and I apologize for using Elixir instead or Erlang for the examples.

Thanks,
Stefan

Thanks for reporting this issue.

The ASN.1 compiler ignored the SIZE constraint in:

TextLines ::= SEQUENCE (SIZE (1..4),...) OF Text

This bug can be avoided by rewriting the constraint like this:

TextLines ::= SEQUENCE (SIZE (1..4, ...)) OF Text

which is the recommended way to write such constraint.

This pull request fixes the bug. It will be included in OTP 26.1.

2 Likes

Thanks so much for the help!

Rewriting the constraint within the schema, did solve the issue. And it is seemingly still compatible with the non modified Schema.

Thanks
Stefan