[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
RE: C-Backend: Bug in choice decoding with indefinite lengths
Well... That may be technically correct ASN.1, but it sure doesn't make
sense to me :-) If there is a bug in eSNACC handling that I'd say leave it
there so that we catch stuff like this.
The context specific [1] on the CHOICE is useless. Remove it and I'm sure
your problem will go away. The question is why you think you need it. If
you're just playing around that's cool, but you should never have the need
for a context specific tag on the CHOICE itself. However, you must tag the
members of the CHOICE if it's to be used in a context where the resulted tag
set is not unique. Your example below you doesn't need tags on members of
the CHOICE unless you add INTEGER and/or OCTET STRING to TSeq.
Have Fun,
-Pierce
-----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);