[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: C-Backend: Bug in choice decoding with indefinite lengths



Hi Tom,
I wasn't in the office last week, so my answer is late too. Of course my 
example was no "real" ASN.1 definition. I simply wanted to prove that the 
generated C code contains a bug and not the BER data I'm receiving. The 
complete ASN.1 definition is from an upcoming ETSI standard, so I can't 
simply change it. It spreads over several files and the CHOICE's there are 
always types of their own, but that doesn't change the generated code. 

Do you have any idea, at what time a new release or patch will be released? 
Currently I work with the compiler patch I provided, but of course I would 
appreciate it if this patch would be validated by other people with more 
insight into the esnacc.

Hanspeter

Am Mittwoch, 8. März 2006 17:29 schrieb Horvath, Tom (US SSA):
> Hanspeter,
>
> Sorry I did not get to respond earlier, but while your example is odd,
> it is still valid ASN.1 and the ASN.1 compiler should generate the
> correct code.  I figure you had more a more complex ASN.1 syntax that
> you paired down just for the sake of explaining the problem.  In certain
> circumstances where you have more than one choice and one is marked
> optional and both contain choices of the same types it may make sense to
> tag the choice itself to avoid ambiguity rather than to tag each member
> within the choice.  This approach could result in less explicit tags if
> it means that you only have to tag one item compared to tagging each
> item in the choice.  I understand it is all style so you could go either
> way, but we certainly need to fix the compiler if it is generating bad
> code.  We will incorporate a fix for this into the next patch or
> release.
>
> --Tom
>
> -----Original Message-----
> From: owner-imc-snacc@xxxxxxxxxxxx [mailto:owner-imc-snacc@xxxxxxxxxxxx]
> On Behalf Of Hanspeter Halle
> Sent: Friday, March 03, 2006 5:11 AM
> To: imc-snacc@xxxxxxx
> Subject: C-Backend: Bug in choice decoding with indefinite lengths
>
>
> Hi all,
> I've got decoding errors in PDU's I've received, which had a mixture of
> definite and indefinite lengths. As the complete asn1 definition is a
> bit
> complex I tried to reproduce the problem with an easier one:
>
> TSeq ::= SEQUENCE
> {
>     ch [1] CHOICE
>     {
>         c1 [0] OCTET STRING,
>         c2 [1] INTEGER
>     }
> }
>
>
> The generated code for the sequence looks like this:
>
> ...
>    tagId1 = BDecTag (b, &totalElmtsLen1, env);
>
>     if (((tagId1 == MAKE_TAG_ID (CNTX, CONS, 1))))
>     {
>     elmtLen1 = BDecLen (b, &totalElmtsLen1, env);
>         (v->ch) = (TSeqChoice*)Asn1Alloc(sizeof(TSeqChoice));
>     tagId2 = BDecTag (b, &totalElmtsLen1, env);
>     elmtLen2 = BDecLen (b, &totalElmtsLen1, env);
>     BDecTSeqChoiceContent (b, tagId2, elmtLen2, (v->ch),
> &totalElmtsLen1,
> env);
>     if (elmtLen1 == INDEFINITE_LEN)
>         BDecEoc(b, &totalElmtsLen1, env);
>         if (elmtLen1 == INDEFINITE_LEN)
>         BDecEoc (b, &totalElmtsLen1, env);
>         seqDone = TRUE;
>         if (elmtLen0 == INDEFINITE_LEN)
>             BDecEoc (b, &totalElmtsLen1, env);
>         else if (totalElmtsLen1 != elmtLen0)
>             longjmp (env, -101);
>     }
>     else
>         longjmp (env, -102);
> ...
>
>
> It's obvious that this won't work if indefinite lengths are used,
> because it
> requires 3 EOC's at the end of the PDU having only 2 levels of
> structured
> data. Searching for the the bad code in the C-Backend I found that the
> additional EOC checking needed for tagged choices is generated 2 times,
> one
> time in PrintCElmtDecodeCode and one time after each call to
> PrintCElmtDecodeCode.
> As I guess it's better to handle it at a place, where the length
> decoding is
> done too, I would propose the patch below. This works fine for me, but I
>
> don't know if it imposes problems for other asn1 files.
>
> Hanspeter
>
>
> --- gen-dec.c.org       2004-03-12 19:51:20.000000000 +0100
> +++ gen-dec.c   2006-03-03 10:26:05.000000000 +0100
> @@ -978,16 +978,6 @@
>          if ((builtinType == BASICTYPE_ANY) ||
>              (builtinType == BASICTYPE_ANYDEFINEDBY))
>              PrintEocDecoders (src, elmtLevel, initialElmtLevel,
> itemLenVarNameG, totalLevel, decodedLenVarNameG);
> -        /*
> -         * must check for another EOC for tagged CHOICEs
> -         * since the choice decoder routines do not check
> -         * for an EOC on the choice's overall length -
> -         * they are only passed the tag/len of the choice's
> -         * component.
> -         */
> -        else if ((builtinType == BASICTYPE_CHOICE) &&
> !(stoleChoiceTags) &&
> -                ((tags != NULL) && !LIST_EMPTY (tags)))
> -            PrintEocDecoders (src, elmtLevel, initialElmtLevel,
> itemLenVarNameG, totalLevel, decodedLenVarNameG);
>
>          else
>              PrintEocDecoders (src, elmtLevel-1, initialElmtLevel,
> itemLenVarNameG, totalLevel, decodedLenVarNameG);
> @@ -1345,16 +1335,6 @@
>          if ((builtinType == BASICTYPE_ANY) ||
>              (builtinType == BASICTYPE_ANYDEFINEDBY))
>              PrintEocDecoders (src, elmtLevel, initialElmtLevel,
> itemLenVarNameG, totalLevel, decodedLenVarNameG);
> -        /*
> -         * must check for another EOC for tagged CHOICEs
> -         * since the choice decoder routines do not check
> -         * for an EOC on the choice's overall length -
> -         * they are only passed the tag/len of the choice's
> -         * component.
> -         */
> -        else if ((builtinType == BASICTYPE_CHOICE) &&
> (!stoleChoiceTags) &&
> -                ((tags != NULL) && !LIST_EMPTY (tags)))
> -            PrintEocDecoders (src, elmtLevel, initialElmtLevel,
> itemLenVarNameG, totalLevel, decodedLenVarNameG);
>
>          else
>              PrintEocDecoders (src, elmtLevel-1, initialElmtLevel,
> itemLenVarNameG, totalLevel, decodedLenVarNameG);
> @@ -1678,16 +1658,6 @@
>      if ((builtinType == BASICTYPE_ANY) ||
>          (builtinType == BASICTYPE_ANYDEFINEDBY))
>          PrintEocDecoders (src, elmtLevel, initialElmtLevel,
> itemLenVarNameG,
> totalLevel, decodedLenVarNameG);
> -        /*
> -         * must check for another EOC for tagged CHOICEs
> -         * since the choice decoder routines do not check
> -         * for an EOC on the choice's overall length -
> -         * they are only passed the tag/len of the choice's
> -         * component.
> -         */
> -    else if ((builtinType == BASICTYPE_CHOICE) && (!stoleChoiceTags) &&
> -             ((tags != NULL) && !LIST_EMPTY (tags)))
> -        PrintEocDecoders (src, elmtLevel, initialElmtLevel,
> itemLenVarNameG,
> totalLevel, decodedLenVarNameG);
>
>      else
>          PrintEocDecoders (src, elmtLevel-1, initialElmtLevel,
> itemLenVarNameG, totalLevel, decodedLenVarNameG);
> @@ -1920,16 +1890,6 @@
>          if ((builtinType == BASICTYPE_ANY) ||
>              (builtinType == BASICTYPE_ANYDEFINEDBY))
>              PrintEocDecoders (src, elmtLevel, initialElmtLevel-1,
> itemLenVarNameG, totalLevel, decodedLenVarNameG);
> -        /*
> -         * must check for another EOC for tagged CHOICEs
> -         * since the choice decoder routines do not check
> -         * for an EOC on the choice's overall length -
> -         * they are only passed the tag/len of the choice's
> -         * component.
> -         */
> -        else if ((builtinType == BASICTYPE_CHOICE) &&
> (!stoleChoiceTags) &&
> -                ((tags != NULL) && !LIST_EMPTY (tags)))
> -            PrintEocDecoders (src, elmtLevel, initialElmtLevel-1,
> itemLenVarNameG, totalLevel, decodedLenVarNameG);
>
>          else
>              PrintEocDecoders (src, elmtLevel-1, initialElmtLevel-1,
> itemLenVarNameG, totalLevel, decodedLenVarNameG);