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