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

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);